What It Takes to Scan Half a Million Packages a Day

Every package npm and PyPI publish is an archive somebody has to open. We download them all, screen them in parallel, unpack the ones that need a closer look, and give an agent only what the scanners cannot settle.

Trickest

offensive securityautomationrecon

npm and PyPI publish close to 100,000 packages a day. Each one is an archive holding real files: install scripts that run on the developer's machine, bundled binaries, and whatever the author decided to ship. Nobody reads that stream. A team that opens one suspicious release by hand is behind again by the time it finishes, and the payload it wanted to look at may already be gone.

Our workflow downloads and inspects those archives at about 350 packages a minute, from collection through to a recorded verdict, on 200 machines. That is more than 500,000 a day, or a full day of npm and PyPI releases five times over. The static checks inside it have processed more than 3,000 archives a minute.

None of that comes from a faster scanner. It comes from the shape of the workflow. Collect the publish stream once. Run independent checks together instead of in a queue. Spread archive inspection across workers. Give the agent only the evidence those scanners cannot resolve.

The rest of this post walks that graph one plate at a time, so you can see where each of those numbers comes from. Every canvas below opens another part of the workflow, from the incoming package stream to the final call.

Let Each Check Move at Its Own Speed

Start with a freshly published package. Before opening its files, you can ask whether anyone has reported it, whether its name imitates another project, or whether its maintainer has changed. None of those questions needs to wait for a download.

Our parent workflow gives those checks separate branches:

Workflow Editor
150%

Collect published packages reads the npm and PyPI publish streams and remembers where it stopped. It sends the batch to Check known-malicious, Assess identity risk, and Inspect archives. The branches run together. A merge script joins their output, and Build risk records turns it into evidence for review.

This lets a fast feed lookup finish while a larger archive is still downloading. It also lets us change one scanner without rewriting the whole process.

The boxes tell you what kind of work happens inside:

Tool
Script
Module
Agent

A cyan tool runs a scanner. An orange script prepares or combines data. A purple module contains a smaller workflow you can open. A violet agent reads evidence and makes an assessment. The final parent box, Adjudicate package risk, is a module; its agent sits inside.

These canvases simplify the workflow to make those relationships visible.

Use What Is Already Known

Public intelligence gives you a head start. Check known-malicious looks for reports about the incoming versions and brings them together:

Workflow Editor
150%

OSV provides advisory information and Aikido provides malware-feed claims. We retain the source of each report so the later assessment can distinguish what someone reported from what our inspection found.

That distinction matters when a package disappears. A feed may still describe the incident, even when the files are no longer available. It also matters when a campaign spans several releases: evidence about one version should stay attached to that version.

Alongside those lookups, Assess identity risk examines the package's name and publisher history. Typosquatting, slopsquatting, and unexpected maintainer changes give you reasons to look closer. They guide the investigation without deciding what the code does.

Look Inside the Published Package

The archive holds what a developer would download. That makes it the place to look for install-time payloads, embedded secrets, and suspicious combinations of behavior.

We use a broad static archive pass, then select packages for deeper checks. The archive workflow groups that deeper inspection by the question each scanner answers:

Workflow Editor
150%
  • Inspect contents uses TruffleHog and YARA to find secrets and recognizable signatures.
  • Profile capabilities uses malcontent to show what the files can do.
  • Audit install scripts uses Semgrep to examine code that runs during installation.
  • Scan malware indicators uses GuardDog to find leads, followed by a separate verification step.

Opening these modules reveals a shared pattern: unpack the files, give scanners the inputs they need, and collect their findings.

Workflow Editor
150%

Several weak signals can become useful when you read them together. Network access is ordinary. Launching a subprocess is ordinary. An install script that downloads an unexplained payload and executes it deserves a closer look.

The surrounding code makes the difference. We keep relevant source excerpts with the finding so the next stage can follow the behavior instead of reasoning from an alert label alone.

Make the Expensive Work Parallel

Downloading and inspecting archives is where a growing batch can become a long queue. Sharding divides that batch into smaller groups that workers can inspect at the same time.

Workflow Editor
150%

The planner creates batch ranges. The next step assigns packages to them. Workers scan their slices, and the workflow collects the results into one view.

That is how the static archive pass reaches thousands of archives a minute. The workflow spreads repeated work across workers while keeping each finding tied to its package version. Deeper investigation follows its own pace.

Batch size is the useful control. Small batches spread work more evenly but repeat setup. Larger batches share that overhead, although a slow archive can delay its neighbors. You can tune this balance without changing what the scanner looks for.

The result is a workflow you can widen as volume grows. The scanner stays familiar; the work no longer has to fit through one worker.

Spend Judgment on the Cases That Need It

After scanning, Build risk records brings public reports and file evidence into a dossier for each version. It also records checks that could not finish. That gives the next stage enough context to decide which cases need attention.

Inside Adjudicate package risk, the agent works between preparation and validation:

Workflow Editor
150%

Scripts select risky or unresolved cases and assemble their evidence. A review skill tells the agent how to assess that evidence. Afterward, the workflow checks its answer and merges it back into the package record.

This keeps model review focused. The agent can spend its attention on an ambiguous installer or a hidden payload without reading the entire publish stream. We scale scanner work across workers and control the agent's workload through selection.

It is also why the whole workflow runs at about 350 packages a minute while the archive pass runs at 3,000. Collection pins the exact version of every package before any scanner runs, and the agent reads each selected case in full. Those two stages set the pace. The scanners in between are never the bottleneck.

The evidence requirement carries through to the final call. A feed hit alone cannot establish our malicious verdict. An incomplete agent response leaves the case unresolved. Every selected package keeps a record, including the ones that need another look.

Where This Breaks

Registry limits can slow downloads even when workers are available. Adding machines speeds up the archive pass, not collection, which pins exact versions on a single worker. Disappearing archives leave gaps. Static checks can miss behavior that depends on runtime conditions or a later payload. Filtering test files can also hide relevant code.

Those limits belong in the package record. A completed workflow needs to show what it inspected and what remains unknown. Otherwise, higher throughput just produces confident answers faster.

What This Costs You

You still maintain scanner rules, collection bookmarks, and retry behavior. You also choose how much evidence to retain. A registry link alone will not help when someone removes the package.

We run these workflows on Trickest's fleet and keep the results in queryable tables. The graph makes the method inspectable: you can open a module, change a check, and follow a finding back to the work that produced it.

Broad scanning gives you reach. Selective investigation gives you depth. Keeping the evidence gives the result a useful life beyond the package itself.

Get a personalized demo

See Trickest in Action

A 30-minute walkthrough. We map the platform to your stack and answer pricing and deployment questions for your environment.