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.
Command line
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
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.
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 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 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.
Real output. The verdict decides whether pip is reached at all.
$ 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
$ 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
$ 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
It has no third-party requirements, so it drops into any environment or CI image.
pip install extuno
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_...
Use it exactly like pip. Your usual arguments are passed through untouched.
extuno pip install -r requirements.txt
They cover a different question, and the tools say so themselves.
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".
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.
| Approach | Catches a reported release | Catches an unreported release | Stops the install |
|---|---|---|---|
| Vulnerability scanning (SCA) | yes | no | no |
| Advisory-backed malware check | yes | no | warns |
| Reputation heuristics | partly | partly | yes |
| extuno | yes | yes, by analysing it | yes |
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.
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.
| Package | Date | What it took | Ran at |
|---|---|---|---|
| ctx | May 2022 | Environment variables, AWS keys | import |
| torchtriton | Dec 2022 | SSH keys, /etc/passwd, exfiltrated over DNS | import |
| ultralytics | Dec 2024 | Cryptominer, CI cache poisoning | import |
| soopsocks | Sep 2025 | Windows backdoor, SOCKS5 proxy | runtime |
| litellm | Mar 2026 | Kubernetes tokens, CI/CD secrets | every interpreter start, via .pth |
| lightning | Apr 2026 | GitHub, npm and cloud tokens | import |
| Hades campaign | Jun 2026 | Downloaded a second runtime, forged provenance | import |
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.
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 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.
| Verdict | What it means | Blocks by default |
|---|---|---|
| malicious | In the known-malicious catalog, or analysis proved attack behaviour: code that runs at install time, credentials read then transmitted, a decoded payload executed | yes |
| suspicious | A real attack technique that is dual-use on its own, so a person should look before installing | yes |
| error | The check could not be completed: the release is missing, the scan failed, or the index now serves a different artifact than the one analysed | yes |
| review | Findings worth knowing, such as a leaked-looking secret or a vulnerable pattern, that say nothing about intent | no |
| clean | Neither | no |
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.
This is the property the design is built around, not a feature bolted onto it.
--allow-unassessed.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
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.
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.
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.
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.
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.
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.
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.
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.
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.
Yes. extuno check exits non-zero when a package is blocked, writes SARIF for inline annotations and a JSON report, and never installs anything.
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.
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.