Open API · No key · CC-BY 4.0
Build on the list.
Every known-bad skill, MCP server and package, as signed open data.
Four URLs to read.
-
Feed
GET /feed.jsonEvery record in OSV 1.6 JSON.
-
Signature
GET /feed.json.sigEd25519, checked with /pubkey.pem.
-
SQLite
GET /api/v1/feed-sqlite.phpThe same list as one file, for offline lookups.
-
Hook
GET /hook/threat-cafe-hookA drop-in check for Claude Code. Settings
Try it in ten seconds.
List every known-bad target
curl -s https://threat.cafe/feed.json \
| jq -r '.vulnerabilities[]
| select(.database_specific.verdict == "known_bad")
| .database_specific.target'
Verify the signature
curl -sO https://threat.cafe/feed.json -O https://threat.cafe/pubkey.pem curl -s https://threat.cafe/feed.json.sig | jq -r .signature_b64 | base64 -d > feed.sig openssl pkeyutl -verify -pubin -inkey pubkey.pem -rawin -in feed.json -sigfile feed.sig
Each record carries target, verdict, ioc, OWASP tags and the finder. Browser apps can fetch it from any origin.
Send us a finding.
From a scanner, a bot or a script. A person reviews every one.
Report without a key (Python, standard library)
import hashlib, json, urllib.request
API = "https://threat.cafe/api/intake.php"
# A short puzzle keeps bots out: find n where sha256("challenge:n") starts with `difficulty` zero bits.
ch = json.load(urllib.request.urlopen(API + "?challenge=1"))
n = 0
while int.from_bytes(hashlib.sha256(f"{ch['challenge']}:{n}".encode()).digest()[:4], "big") >> (32 - ch["difficulty"]):
n += 1
report = {"action": "report", "artifact": "npm:[email protected]",
"evidence_url": "https://example.com/write-up", "notes": "Reads ~/.ssh in postinstall",
"credit": "Your name", "pow": {"challenge": ch["challenge"], "nonce": str(n)}}
req = urllib.request.Request(API, json.dumps(report).encode(), {"Content-Type": "application/json"})
print(json.load(urllib.request.urlopen(req)))
With a reporter key, no puzzle
curl -s https://threat.cafe/api/intake.php \
-H 'Authorization: Bearer tcr_your_key' \
-H 'Content-Type: application/json' \
-d '{"action": "report", "artifact": "npm:[email protected]",
"evidence_url": "https://example.com/write-up"}'
The answer
{"ok": true, "receipt_id": "tc_report_3f9a1c2b7d4e",
"artifact": "npm:[email protected]", "remaining_today": 4,
"next": "Sorted by code within 6 hours, read by AI once a day, ..."}
- Any ecosystem
npm,pypi,mcp,clawhub,skillssh,gh,vscode,docker. Version*means all. - Fair limitsA half-second puzzle, then 5 an hour and 20 a day per address. A reporter key skips the puzzle and allows 500 a day.
- People decideNothing is listed on a report alone.
"action": "audit"asks us to check an unknown item; disputes use"action": "dispute".
Three rules.
- Never "safe".Show known bad, no known bad or unknown.
- Give credit.Name threat.cafe and the finder (CC-BY 4.0).
- Stay fresh.Refresh before the feed's
expirestime.