For engineers shipping LLM & AI-agent apps

Your AI app fetches URLs, runs tools, and loads models. Attackers noticed.

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.

One-time. Instant PDF + copy-paste code repo + 9 exploit walkthroughs. No subscription.
SSRFPrompt injection Unsafe deserialization (pickle / torch.load) Path traversalMissing auth Secret management

The free checklist — 12 of 48 checks

Every one of these maps to a real vulnerability class I've reproduced in production-grade AI OSS. Fix these before launch.

1. Block SSRF in every fetch tool Critical

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.

2. Never pickle.load / torch.load untrusted Critical

Model 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.

3. Isolate tool execution from prompt content Critical

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.

4. Put auth on the websocket, not just the UI High

Streaming /ws endpoints frequently ship with zero auth because "the frontend is behind login." The socket is directly reachable. Authenticate the connection itself.

5. Sanitize file paths in up/downloads High

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.

6. No user input in 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.

7. Generate secrets per-install; blocklist defaults High

A hardcoded default JWT_SECRET/SECRET_KEY lets anyone forge admin sessions. Fail to boot on the placeholder value; auto-generate on first run.

8. Bound every input; reject weird types/sizes Medium

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.

9. Don't reflect request data unescaped Medium

Echoing a query or model output into HTML without escaping is stored/reflected XSS — worse when the model can be steered into emitting markup.

10. Rate-limit + cap spend per key High

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.

11. Keep secrets out of responses & logs High

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.

12. Pin & audit your dependency + model supply chain Medium

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.

One fix, in full

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.

The Production Security Pack — $19

Everything below, delivered as a PDF + a code folder you can paste straight into your project.

  • The full 48-point checklist — each with severity, a copy-paste "am I vulnerable?" grep, and the fix.
  • Copy-paste hardening code — SSRF guard, safe model/deserialization loader, path-traversal-safe file handler, websocket auth, secret bootstrap, spend cap.
  • 9 exploit walkthroughs — real vulnerability patterns I reproduced in open-source AI projects, with the request that triggers them and the diff that closes them.
  • A 15-minute pre-launch review script — the greps and manual checks I run before an AI app ships.
  • One-time payment. Free updates. Built for FastAPI/Flask + the LangChain / LlamaIndex / gradio ecosystem.

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).

Who makes this

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.