Command line

The gate goes in front of
pip install

A package gets to run code on your machine at two moments: while pip builds a source distribution, and the first time your program imports it. Both run as you, with your credentials and your network. extuno answers before either one, and the package itself never reaches your machine to be answered about.

pip install extuno Python 3.9+ · zero dependencies · MIT

Does pip install actually run code?

It depends on what pip fetched, and the honest answer has two halves. This is the detail most write-ups skip, and it is why a check that only looks at one half misses most real incidents.

A source distribution: yes, at install

An sdist ships a setup.py that pip executes to produce the metadata and the build. Anything in that file runs during pip install, before your program does anything at all.

A wheel: not at install, but at import

A wheel is installed by unpacking, so nothing executes during the install itself. The code still runs the moment you import the package, which for a dependency you actually use is seconds later.

A .pth file: at every interpreter start

A .pth file placed in site-packages is executed by Python on startup. The litellm compromise of March 2026 used exactly this: the payload ran on every interpreter launch even if the package was never imported.

Most of the well known PyPI compromises fired at import rather than at install. The PyTorch advisory for torchtriton states it plainly: the malicious binary ran when the package was imported. So the useful question is not which of the two moments a payload picks. It is whether anything gets decided before the code is on your disk at all.

Three outcomes, one command

Real output. The verdict decides whether pip is reached at all.

first time seenone credit
$ extuno pip install six
  - six 1.17.0 ........................ sha256 ff70335d468e7eb6
  - checking Extuno ................... not analysed yet
  - scan queued ....................... 1 credit 0738cabf
  - downloading package ............... in the isolated environment
  - dynamic analysis .................. running in the sandbox
  - analysis complete
  verdict CLEAN  risk 0/100

OK verdicts acceptable, installing
Successfully installed six-1.17.0
already knownfree, under a second
$ extuno pip install requests
  - requests 2.34.2 ................... sha256 f288924cae4e2946
  - checking Extuno ................... already analysed, no credit used
  verdict CLEAN  risk 0/100

OK verdicts acceptable, installing
blockedpip is never reached
$ extuno pip install <package from the catalog>
  - checking Extuno ................... listed in the malicious database
  verdict MALICIOUS
    malicious-package  Listed in the Datadog malicious-software-packages dataset

BLOCKED 1 of 1 package(s) blocked
$ echo $?
1

Install and first run

  1. Install the tool

    It has no third-party requirements, so it drops into any environment or CI image.

    pip install extuno
  2. Authenticate once

    Create an API key in the console. The key is stored with owner-only permissions; in CI set EXTUNO_API_KEY and skip this step.

    extuno login --key extk_...
  3. Put it in front of pip

    Use it exactly like pip. Your usual arguments are passed through untouched.

    extuno pip install -r requirements.txt

Does uv audit or pip-audit already cover this?

They cover a different question, and the tools say so themselves.

Advisory lookups answer "is this release reported"

pip-audit matches your installed versions against known vulnerability records and states that it is not a static code analyser. Astral's uv audit adds a malware check and names its own boundary: the check "relies on public advisories", so malware "is typically not detected immediately after it becomes publicly visible".

Extuno answers "what does this release do"

A release nobody has reported yet has no advisory to match. Extuno analyses the artifact itself: static rules over the source, then the install path executed under an audit hook in a disposable microVM, then a reading pass over the entry points.

ApproachCatches a reported releaseCatches an unreported releaseStops the install
Vulnerability scanning (SCA)yesnono
Advisory-backed malware checkyesnowarns
Reputation heuristicspartlypartlyyes
extunoyesyes, by analysing ityes

The two are complements, not substitutes. Keep your advisory scanner for the CVEs in what you already run; put this in front of what you are about to add. See the longer comparison in Extuno versus package supply-chain scanners.

What this class of attack has looked like

Every row is a documented PyPI compromise, with the moment the payload actually ran. The pattern worth noticing: the execution point moves, so a check tied to one of them is a check with a blind spot.

PackageDateWhat it tookRan at
ctxMay 2022Environment variables, AWS keysimport
torchtritonDec 2022SSH keys, /etc/passwd, exfiltrated over DNSimport
ultralyticsDec 2024Cryptominer, CI cache poisoningimport
soopsocksSep 2025Windows backdoor, SOCKS5 proxyruntime
litellmMar 2026Kubernetes tokens, CI/CD secretsevery interpreter start, via .pth
lightningApr 2026GitHub, npm and cloud tokensimport
Hades campaignJun 2026Downloaded a second runtime, forged provenanceimport

Volume is not the story. ReversingLabs reported that malware found on PyPI fell 43 percent over the past year while npm roughly doubled. What rose on PyPI is targeting: AI and ML packages, CI credentials, and forged supply-chain provenance. The OpenSSF malicious-packages dataset currently records over 11,000 PyPI entries, and Extuno checks every request against that catalog plus its own, at no cost and with no scan.

When an agent runs the install, not a person

A coding agent that writes and then runs pip install removes the one review step this ecosystem relied on: someone reading the package name before pressing enter.

Language models invent dependency names. A USENIX Security 2025 study generated 576,000 code samples across 16 models and found 205,474 unique hallucinated package names, at 5.2 percent of recommendations from commercial models and 21.7 percent from open ones. Attackers register the names that recur, so the agent's invented import resolves to a real, hostile package. The paper's own recommendation is a two-step flow where the install the agent proposes is confirmed before it runs.

That is what this tool is, expressed as a command. Point the agent at extuno pip install instead of pip install, and every package it reaches for is assessed before it lands, with the decision recorded rather than assumed.

A verdict is not a risk score

A widely used library that ships an integration test suite, a throwaway certificate, and a permissive TLS option scores high. None of that is evidence of intent, so it does not block an install. A pre-install gate that cries wolf gets removed from the pipeline within a week.

VerdictWhat it meansBlocks by default
maliciousIn the known-malicious catalog, or analysis proved attack behaviour: code that runs at install time, credentials read then transmitted, a decoded payload executedyes
suspiciousA real attack technique that is dual-use on its own, so a person should look before installingyes
errorThe check could not be completed: the release is missing, the scan failed, or the index now serves a different artifact than the one analysedyes
reviewFindings worth knowing, such as a leaked-looking secret or a vulnerable pattern, that say nothing about intentno
cleanNeitherno

Raise the bar with --fail-on malicious,suspicious,review,unknown when a pipeline should stop on anything unresolved. The rules behind these verdicts are documented in the detection rule set.

Nothing hostile runs on your machine

This is the property the design is built around, not a feature bolted onto it.

  • The artifact is never fetched locally. The tool reads the index's JSON metadata to learn the version and digest. Nothing is downloaded, unpacked, imported, or executed on the developer's machine.
  • Analysis runs in a disposable microVM. Extuno fetches and detonates the package inside a network-segmented virtual machine that is destroyed after every run, with a decoy home directory so only fake credentials are ever there to steal.
  • requirements.txt is parsed as text. pip's resolver is not used for the assessment, because resolving a source distribution can execute its build backend, which is the event this tool exists to get in front of.
  • Unassessable arguments stop the install. A direct URL, a local path, an editable, or an index override cannot slip past the gate unchecked; they halt the run unless you pass --allow-unassessed.
  • No dependencies of its own. The package installs with zero third-party requirements. A supply-chain tool that pulls in a dependency tree adds the risk it was brought in to remove.

Built for the pipeline

extuno check never installs anything. It assesses, writes machine-readable output, and sets an exit code.

- name: Supply-chain gate
  env:
    EXTUNO_API_KEY: ${{ secrets.EXTUNO_API_KEY }}
  run: |
    pip install extuno
    extuno check -r requirements.txt \
      --sarif extuno.sarif --json report.json

- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: extuno.sarif

Exit codes

0
nothing blocked
1
a package was blocked by policy
2
usage, network, or server error
3
out of scan credits
4
a scan did not finish in time

SARIF 2.1.0 for inline annotations on GitHub, GitLab, and Azure DevOps. --no-scan runs entirely on what is already known and spends nothing, which suits a pull request check that must never block on a queue. The same gate covers secrets in the repository itself.

Questions people actually ask

Does pip install actually run code?

For a source distribution, yes: pip executes setup.py during the install. For a wheel, no, the install only unpacks files, but the code runs at your first import, and a .pth file in the package can run on every interpreter start. All three are on your machine, as you.

Do wheels protect me from install-time code?

They remove the build step, not the risk. Most documented PyPI compromises ran at import rather than at install, so a wheel-only policy narrows the window without closing it.

How do I check whether a PyPI package is malicious before installing it?

Run extuno pip install <package> instead of pip install <package>. The exact release is checked against the known-malicious catalog and against previous analysis; an unseen release is analysed in an isolated environment, and the install proceeds only when the verdict allows it.

Does the package run on my machine during the check?

No. The tool reads index metadata to learn the version and digest. The artifact is fetched and analysed by Extuno inside a network-segmented ephemeral virtual machine.

Does uv audit already protect me?

It helps with what has already been reported. Astral documents that its malware check relies on public advisories, so a release that has not been reported yet has nothing to match against. Extuno analyses the artifact itself, which is what covers the window between publication and disclosure.

What is the difference between this and pip-audit or Safety?

Those answer whether a version you have appears in a vulnerability database. This answers what a version you are about to add actually does, and refuses to install it when the answer is bad. They solve different halves and work well together.

Can it stop a package my coding agent tried to install?

Yes, and that is a growing reason to use it. Models hallucinate dependency names that attackers pre-register, so an agent's install can resolve to a hostile package with no person in the loop. Give the agent extuno pip install and the decision is made before anything lands.

What happens when a release has never been scanned?

The tool submits it for analysis and follows the scan to completion, printing each stage. That costs one scan credit. Every later request for the same release is served from the result, free and immediately.

Does it work in CI?

Yes. extuno check exits non-zero when a package is blocked, writes SARIF for inline annotations and a JSON report, and never installs anything.

What does it cost?

Checking a release Extuno already knows is free and instant. Analysing a release for the first time costs one scan credit, and new accounts start with five.

Put it in front of your next install

New accounts start with five scan credits. Checking a release Extuno already knows stays free. The same analysis backs PyPI scanning in the console and the other eleven ecosystems.

pip install extuno Create an account View on PyPI