I do security research on open-source AI projects — SSRF in agent frameworks, RCE via unsafe model loading, auth you can walk straight through. This is the exact checklist I run before an AI app touches the public internet, plus the copy-paste code to fix each hole.
Every one of these maps to a real vulnerability class I've reproduced in production-grade AI OSS. Fix these before launch.
Agents that fetch user-supplied URLs (research tools, RAG loaders, webhook callers) will be pointed at 169.254.169.254 to steal cloud IAM creds. Resolve the host, reject private / link-local / metadata ranges after DNS resolution, and re-check on redirects.
pickle.load / torch.load untrusted CriticalModel files, checkpoints, and cached embeddings are code-execution payloads when unpickled. Use safetensors, or torch.load(..., weights_only=True), and treat every uploaded .pt/.pkl/.bin as hostile.
Treat all model input — retrieved docs, tool output, user text — as attacker-controlled. It will try to make the agent call privileged tools. Gate every side-effecting tool behind an allowlist and explicit confirmation, never behind the model's judgment.
Streaming /ws endpoints frequently ship with zero auth because "the frontend is behind login." The socket is directly reachable. Authenticate the connection itself.
Report exporters and file loaders that join user input into a path give arbitrary read/write via ../. Resolve the final path and assert it stays inside the intended directory — don't trust os.path.basename alone.
eval/exec/shell Critical"Code interpreter" and "run this query" features are RCE unless sandboxed. Never build a shell/SQL string by concatenation; use argument arrays and parameterized queries; run generated code in a locked-down sandbox, never the app process.
A hardcoded default JWT_SECRET/SECRET_KEY lets anyone forge admin sessions. Fail to boot on the placeholder value; auto-generate on first run.
Validate length, type, and count on every field an attacker touches. Unbounded prompt / batch / file inputs are DoS and cost-amplification vectors on a metered LLM API.
Echoing a query or model output into HTML without escaping is stored/reflected XSS — worse when the model can be steered into emitting markup.
An open LLM endpoint is a free GPU/token faucet. Per-IP and per-key rate limits plus a hard monthly spend cap stop a scraper from running up your provider bill overnight.
Verbose error handlers and debug endpoints leak API keys, prompts, and stack traces. Strip secrets from logs; disable debug in prod; never echo config back.
Config-driven pip install, unpinned deps, and models pulled from arbitrary hubs are supply-chain RCE. Pin versions, verify hashes, restrict where models load from.
…the pack has all 48, each with the exploit, the one-line "am I vulnerable?" grep, and the fix.
Here's check #1 done properly — the SSRF guard I drop into agent fetch tools. This is the level of detail every one of the 48 gets in the pack.
import ipaddress, socket
from urllib.parse import urlparse
_BLOCKED = [ipaddress.ip_network(n) for n in (
"0.0.0.0/8","10.0.0.0/8","100.64.0.0/10","127.0.0.0/8",
"169.254.0.0/16","172.16.0.0/12","192.168.0.0/16","::1/128","fc00::/7","fe80::/10",
)]
def assert_safe_url(url: str) -> str:
p = urlparse(url)
if p.scheme not in ("http", "https"):
raise ValueError("scheme not allowed")
host = p.hostname
if not host:
raise ValueError("no host")
# resolve ALL addresses the host maps to (defeats DNS-rebinding to internal IPs)
for fam, _, _, _, sockaddr in socket.getaddrinfo(host, None):
ip = ipaddress.ip_address(sockaddr[0])
if any(ip in net for net in _BLOCKED) or ip.is_private or ip.is_loopback \
or ip.is_link_local or ip.is_reserved:
raise ValueError(f"blocked internal address: {ip}")
return url
# call assert_safe_url(u) before EVERY fetch, and re-check after each redirect.
The pack version also handles redirect re-validation, IPv4-mapped IPv6 bypasses, and a drop-in requests/httpx wrapper.
Everything below, delivered as a PDF + a code folder you can paste straight into your project.
Secure checkout via Stripe. After payment, the download link is emailed to you (usually within a few hours — send your Stripe receipt to the address on the receipt if you don't see it).
I'm a security researcher focused on the open-source AI/ML ecosystem — agent frameworks, RAG tooling, model servers, inference UIs. The checks here aren't theoretical; they come from actually reproducing these bugs in real projects. If you're shipping something with an LLM in the loop, this is the 20% of the work that stops the incident.