Modern software is mostly other people's software. A small project declares a handful of dependencies — packages it downloads and runs — and each of those brings its own, and so on, until the code you actually ship is mostly code you never wrote. A scanner that looks only at the files in front of it answers a narrow question: is this file hostile? That is a useful question, and Atomdrift Scan has answered it well. But it is not the question a supply-chain attacker forces you to ask. The list of packages a project declares is almost always clean. The malware is a few levels down, inside something that list merely names. v2.2.0 closes that gap.
It now checks what your project pulls in, and it does so by default. Point
atomscan at a project and it no longer stops at the files you gave it. It
reads the packages the project declares, along with anything its install
commands would fetch, downloads them, and scans them too. Making this the
default was deliberate. A safety check you have to remember to turn on is a
safety check that will be forgotten, and those downloaded packages are exactly
where a careful attacker hides.
Fetching other people's code is not free, and the obvious cost is time. v2.2.0
spends it carefully. A bloom filter sits in front of the real work — a compact
structure that answers, in one cheap lookup, whether a file might be in a set or
is definitely not. Every candidate is checked this way against sets of code
already known to be good or bad before anything expensive happens, and anything
already known to be safe is skipped. You choose how thorough to be with --mode
— fast trusts the filters and stops there, balanced is the default, and
slow always does a full scan. Results are remembered by the exact contents of each file, so a
package that shows up in several places is examined once, and the downloading
and scanning happen at the same time. The second look at a shared set of
dependencies costs almost nothing.
The command has a new name and two shortcuts. The tool is now called
atomscan. The old name, ascan, clashed with a command from Avast's
antivirus, and a name that quietly shadows another program is worth retiring;
the old names still work. Two new shortcuts skip the download-it-yourself step,
which was never really part of the analysis and only invited mistakes:
atomscan purl npm/[email protected] scans a package straight from its name and
version, and atomscan url scans a file sitting at a web address without your
having to save it first.
It now understands file formats it couldn't a month ago — and no scanning code had to change. This is worth a short explanation, because the reason is built into how the tool is put together. Scan does not read files itself. cleave takes a file apart, filefacts reads the raw bytes, and Scan decides what the two of them report. So when cleave 2.2.0 and filefacts 1.2.0 learned to read WebAssembly, Android apps, several archive and container formats, and Python source packages, Scan started catching malware in all of them, untouched. That is the payoff of drawing the line in the right place: the part that judges gets wider every time the part that reads does.
A verdict now points at the evidence behind it. Every observation the
engine makes is tagged with the exact stretch of bytes it came from, so a
hostile verdict can be traced back to the precise part of the file that
earned it. This matters more than it sounds. A verdict you can't inspect is one
you have to take on trust, and trust is not something a security tool should ask
for. The clearest example is filefacts' new trick of measuring randomness in
small windows across a file: it can flag a tiny scrambled region hidden inside
a file that looks perfectly ordinary when measured all at once — an encrypted
payload tucked inside an innocent-looking decoy, which a single whole-file
number sails right past. The warning levels were retuned in the same work, and
a verdict where the machine-learning model is confident but can't show why is
now held back as merely suspicious rather than cleared. Being unable to
explain itself is a reason to look closer, not a free pass.
And it's faster underneath all of it. stng v1.7.1 lets the whole
pipeline share one copy of the text pulled out of a file, instead of each step
pulling it out again, and it fixes a slowdown that used to turn large files into
a long wait for no good reason. Rules and models quietly update themselves when
they fall out of date, so the tool stays current without being told to;
--no-update turns that off.
Release notes: scan v2.2.0 · cleave v2.2.0 · stng v1.7.1 · filefacts v1.2.0.
brew upgrade atomdrift/tap/atomdrift-scan atomdrift/tap/cleave atomdrift/tap/stng atomdrift/tap/filefacts