API & docs
Detonate a package from code, look up a verdict before you install, or gate your CI on it.
Look up a verdict
Free, no key needed. Returns the latest public report for a package.
curl "https://detonationlabs.com/api/v1/lookup?target=npm:@scope/server-name"
Detonate a package
Targets: npm:<package>[@version], pypi:<package>, clawhub:@owner/skill (an OpenClaw skill on ClawHub; a pasted openclaw skills install @owner/skill command or a clawhub.ai link works too), or a https://github.com/owner/repo URL. Without a key you get a few scans an hour; with a key, a monthly quota.
curl -X POST https://detonationlabs.com/api/v1/scans \
-H "Authorization: Bearer $DETONATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"target": "npm:@scope/server-name", "public": true}'
Upload a private zip (a skill folder or a server):
curl -X POST https://detonationlabs.com/api/v1/scans \ -H "Authorization: Bearer $DETONATOR_API_KEY" \ -F [email protected] -F public=false
Both return 202 with a scan id. A package scanned publicly in the last 7 days returns the cached report straight away ("cached": true).
Get the result
curl https://detonationlabs.com/api/v1/scans/<id>
| field | meaning |
|---|---|
status | queued → running → done or failed |
verdict | MALICIOUS BEHAVIOR OBSERVED, VULNERABLE (exploitable by others, not hostile itself), SUSPICIOUS, NO MALICIOUS BEHAVIOR OBSERVED or COULD NOT RUN |
progress | runs finished so far, with their findings |
report | the full report: findings with evidence, observed manifest, every run |
report.startup | MCP servers: the args, environment variable names (values shown as <fake>) and files we supplied to start it |
report.partial_scan | set when only the package itself could be installed (dependencies over the size limit) |
report_url | the human-readable report page |
Gate CI on it
Fail a build when a dependency or a new MCP server shows malicious behavior:
v=$(curl -s "https://detonationlabs.com/api/v1/lookup?target=npm:$PKG" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("verdict",""))')
[ "$v" = "MALICIOUS BEHAVIOR OBSERVED" ] && { echo "blocked: $PKG"; exit 1; }
Search
curl "https://detonationlabs.com/api/v1/search?q=github&verdict=malicious"
How MCP servers are tested
- Smart start. Many servers refuse to start without a flag, an environment variable or a config file. We start them the way their README's
mcpServersexample says, and if the handshake still fails we read the error output and supply what it asks for (a required--flag, a missing variable, a placeholder config file), up to 3 retries. Secret-looking values are fake keys carrying unique markers, and paths point to folders inside the sandbox. The report says exactly what was supplied ("Started with --data-dir ./data and a fake GITHUB_TOKEN") in thestartupfield. A configured key sent to its own service is expected; sent anywhere else, it is a finding. - Every component. Every tool is called with schema-valid arguments, every resource is read (plus a sample URI per resource template), and every prompt is fetched with generated arguments. All of that text is scanned for injected instructions. In the AI agent test the model also gets the server's resources and prompts, the way a real client presents them, so an instruction split between a prompt and a tool result is tested too.
- Realistic API answers. The sandbox's network sink answers HTTP(S) requests with plausible JSON containing a credential-looking value (
access_token,api_key) that carries a unique marker per host. If a value one host handed out is later sent to a different host, the report says "Data received from one service was forwarded to another". - Intent vs behavior. Each tool gets an expected profile from its name and description (a calculator needs no network, no programs and no files outside the project). Programs, connections and file access seen while a call was running are matched to that tool; a clear mismatch is a medium finding, never more.
- Vulnerability probes (OWASP MCP05, MCP07). On the normal run, each tool's text inputs are also sent as booby-trapped values that ask for a uniquely named file to be created, as a shell command, as Python and as JavaScript. If the file appears, the tool runs its input: command injection. Path inputs get two planted canary files, one by full path and one through
../; a tool that refuses the first but opens the second walks out of its folder: path traversal. Tools whose job is to run commands are not probed for that. If the server opens a port on all network interfaces, we send it an MCP request with no login; if it answers, anyone on the network could use its tools. These findings make the verdict Vulnerable, never Malicious. - Partial scans. When a PyPI package's dependencies are larger than the scan limit (for example PyTorch), the package itself is still scanned: its own code, its install step in the sandbox, and an attempt to start it. The report is labeled
partial_scan. - ClawHub skills. OpenClaw skills are downloaded the way
clawhub installdoes and detonated as skills. Environment variables a skill declares in its metadata (requires.env,primaryEnv) are set to fake keys in their own run, the way a real user would have them: sent to the skill's own service that is expected, sent anywhere else it is a finding. - Limits. Each sandbox may use 3 GB of memory; a package that needs more fails its own run with a note. Password-protected zips are refused with a clear error.
What a verdict means
Malicious behavior observed: we saw it happen, e.g. a planted credential leaving the sandbox, a persistence write, or an agent tricked into passing secrets (confirmed by a control run). Vulnerable: it did nothing harmful itself, but we proved someone else can make it: our input ran as a command, it left its folder, or its network port answered without a login. Suspicious: risky behavior or manipulative text without observed harm. No malicious behavior observed: nothing bad happened in our runs. That is evidence, not a guarantee: code paths we didn't reach can still hide behavior.
API keys
We're onboarding design partners now. Email [email protected] for a key.