How to check packages before installing them, step by step with curl
Last updated: 2026-10-13
To check that a package an LLM suggested really exists, send up to 10 names to POST /v1/check/packages (US$0.005 per batch). AttestPage looks each name up in its registry (npm, PyPI or crates.io) and returns whether it is listed, the latest version, the description, the licence, the links, a few flags and any known advisories from OSV.dev, under one signed receipt.
This guide runs the check with curl and jq against https://vehcdj664efetfrsolne5umanq.srv.us, then shows the same call as an MCP tool. For the kinds of package problem to look for, see Check packages.
What the check does
- Looks up each name. It asks the registry for each name in the ecosystem you give.
existsistruewhen the registry lists it,falsewhen it does not, andnullwhen the lookup failed. - Reports what the registry says.
latest_version,description,license,homepage,repository,created_at,deprecatedandyankedcome from the registry, as the publisher wrote them. - Adds known advisories.
vulnerabilitieslists the OSV.dev advisories for the version you send, or for the latest version when you send none.countis the number of advisories found. - Signs a receipt. One Ed25519 receipt covers the whole batch.
The check answers "is this name listed in the registry". It is not a security verdict. A listed package can still be malicious, unmaintained or not the one you meant, and no advisory listed does not mean the package has no flaws.
Price
US$0.005 per batch of 1 to 10 names, paid in USDC with x402 v2 on Base mainnet (real USDC). No account, key or sign-up. A request that fails validation gets 400 before payment and is never charged, and a batch where every registry lookup fails gets 502 and is not charged. All prices: pricing.json.
1. See an answer for free
The free sample checks four demo names: two that are listed, one listed with an advisory, and one that does not exist.
curl -s https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/packages | jq '.results[] | {name, exists, latest_version, advisories: .vulnerabilities.count}'
{
"name": "left-pad",
"exists": true,
"latest_version": "1.3.0",
"advisories": 0
}
{
"name": "requests",
"exists": true,
"latest_version": "2.32.3",
"advisories": 1
}
{
"name": "serde",
"exists": true,
"latest_version": "1.0.210",
"advisories": 0
}
{
"name": "left-pad-demo-missing",
"exists": false,
"latest_version": null,
"advisories": 0
}
2. Read the price from the 402 offer
Put the names you plan to install in a file. A request with a valid body gets the payment offer without being charged. The PAYMENT-REQUIRED header is base64 JSON:
cat > packages.json <<'EOF'
{ "packages": [{ "ecosystem": "npm", "name": "left-pad" }, { "ecosystem": "pypi", "name": "requests" }] }
EOF
curl -si -X POST https://vehcdj664efetfrsolne5umanq.srv.us/v1/check/packages -H 'content-type: application/json' -d @packages.json \
| grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' | base64 -d \
| jq '.accepts[0] | {scheme, network, amount, payTo}'
amount is in USDC base units (6 decimals), so 5000 is US$0.005.
3. Check the names
Each name needs an ecosystem (npm, pypi or crates) and a name. You may add a version to a name to ask about that version's advisories. Put the batch in the same packages.json as step 2:
cat > packages.json <<'EOF'
{ "packages": [{ "ecosystem": "npm", "name": "left-pad" }, { "ecosystem": "pypi", "name": "requests" }] }
EOF
Pay with any x402 v2 client: it reads the offer from step 2, signs it and sends the same request again with a PAYMENT-SIGNATURE header. One x402 payment step by step shows this with plain fetch, and the MCP server does it for you. Save the answer as answer.json for the steps below.
4. Read the answer
Check exists first, then latest_version and homepage against the package you meant to install, then vulnerabilities for the version you will use:
jq '.results[] | {name, exists, latest_version, homepage, advisories: .vulnerabilities.count}' answer.json
exists | What it means |
|---|---|
true | The registry lists the name. Compare its description and homepage with what the model said it was. |
false | The registry does not list the name. Do not install it: the model may have invented it. |
null | The lookup failed. The name is unchecked, not missing. Try again later. |
Each advisory in vulnerabilities.items has an id, a summary, a severity and the fixed versions. A malicious flag marks an OSV malicious-package record.
5. Keep the receipt
The receipt field is a compact JWS. Keep it with the answer. Check it with the free verify route:
jq '{receipt}' answer.json \
| curl -s -X POST https://vehcdj664efetfrsolne5umanq.srv.us/v1/receipt/verify -H 'content-type: application/json' -d @- | jq .valid
With MCP
The same check is the MCP tool attestpage_check_packages, with the body from step 3 as its arguments. To use it from an MCP client with nothing to install, add the remote endpoint:
{
"mcpServers": {
"attestpage": { "type": "http", "url": "https://vehcdj664efetfrsolne5umanq.srv.us/mcp" }
}
}
One call to the remote endpoint with curl. _meta["attestpage/trial"] set to false asks for the payment offer rather than a trial call, so nothing is charged:
curl -s -X POST https://vehcdj664efetfrsolne5umanq.srv.us/mcp -H 'content-type: application/json' -d @- <<'EOF' \
| jq '.result.structuredContent.accepts[0] | {scheme, network, amount}'
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": { "name": "attestpage_check_packages",
"arguments": { "packages": [{ "ecosystem": "npm", "name": "left-pad" }, { "ecosystem": "pypi", "name": "requests" }] },
"_meta": { "attestpage/trial": false } } }
EOF
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "5000"
}
The result has isError: true and the x402 payment requirements in structuredContent, with the same amount as step 2. Sign one of accepts, put the payload in _meta["x402/payment"] and call again: structuredContent is then the same JSON as answer.json, and _meta["x402/payment-response"] holds the settlement.
Questions
How much does a check cost?
US$0.005 per batch of up to 10 names. Checking 23 names takes 3 batches, so 3 calls.
Is a batch charged if a lookup fails?
Yes, when the batch is checked. A failed lookup is a result, and exists is null for it. A request that fails validation, and a batch where every registry lookup failed, are never charged.
Does exists: true mean the package is fine to install?
No. It means the registry listed the name when we looked. Check the publisher, the homepage and the advisories yourself before you install it.