Menu

Star on GitHub · 3.2k
All posts
Case Studies

SSRF through an AI chat's document-by-URL fetch

Same product, a smaller bug with a longer reach. The AI chat let any member attach a document by URL — and the server fetched almost any URL they gave it. LiteLLM blocked the scary targets, so we rate it honestly: a MEDIUM, not a headline.

A robotic arm reaching out to grab a server — point it at a URL and it fetches: server-side request forgery through an AI chat's document-by-URL fetch

About these case studies. Every finding in this series is a real vulnerability CyberStrike discovered in a live penetration test. Customer names, hostnames, and any detail that could identify the target have been removed under the confidentiality agreement that governs the engagement. The technique, the impact, and the lesson are exactly as we found them — only the target is deliberately unidentifiable.

The same engagement that produced an authenticated RCE through the agent’s execute tool also turned up a quieter bug in the same chat feature — smaller in blast radius, but a clean illustration of how AI features grow server-side reach you didn’t mean to expose.

Severity: MEDIUM · CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N (4.3) · CWE-918 (SSRF) · vector: request body.

CyberStrike finding card — MEDIUM severity SSRF via a multimodal document URL in an AI chat, CWE-918, with the target host redacted

What we found

The chat endpoint accepts multimodal message parts where a document’s “source” is a URL. When a member sends one, the server — through LiteLLM / deep-agents — fetches that URL server-side and feeds the content to the model, which then reflects it back in its reply. Point a document part at any public URL and you read the response through the model’s answer.

That’s textbook server-side request forgery: the server makes the request for you, from its own network position and IP, to a destination you choose.

What it can and can’t do

Credit where it’s due — the dangerous targets are already blocked. LiteLLM’s URL policy refuses cloud metadata (169.254.169.254) and RFC 1918 private ranges, so this is not the metadata-to-IAM-credentials SSRF that makes the news. We rate it the way it actually behaves: a MEDIUM, low confidentiality impact, nothing on integrity or availability.

What’s left is still worth closing:

  • Arbitrary outbound requests from the server’s IP. The application can be made to fetch attacker-chosen URLs — useful for abuse, for pivoting to third parties that trust the server’s egress address, and for reaching internal services that are routable but don’t live in an RFC 1918 block the denylist knows about.
  • An internal-address oracle. Differences in response, error, and timing let an attacker infer what is reachable from inside, mapping the environment one request at a time.

Why a blocklist isn’t the whole fix

Blocking metadata and RFC 1918 is the right instinct, but a denylist is a floor, not a ceiling — it stops the destinations you thought of. The durable fix decides what the fetch is allowed to reach:

  • Allowlist, or proxy through a locked egress. Let the feature reach only the destinations it legitimately needs, or route document fetches through a dedicated egress that can touch the public internet and nothing internal.
  • Resolve, validate, then pin. Resolve the hostname, check the resolved IP against policy, and connect to that exact IP — which defeats the DNS-rebinding and time-of-check/time-of-use tricks that walk straight past a name-based blocklist.
  • Don’t reflect fetched content you don’t need. The oracle runs on the model faithfully reading back whatever it retrieved; if the feature doesn’t need to echo the body, don’t.
  • Rate-limit and log outbound fetches per member, so one-request-at-a-time network mapping is visible and expensive instead of silent and free.

The pattern

It’s the same lesson as the execute-tool RCE from this engagement, one notch quieter: an AI feature quietly grew a server-side capability — here, “fetch a URL for the user” — and the thing that chooses how to use it takes its instructions from the user. Every capability you hand a model is attack surface, because the input is the attacker’s to write. The fix is the same shape too: put the boundary in the system — where the fetch is allowed to go — not in a list of places it isn’t.

Found by CyberStrike — AI-powered security testing. Target and identifying details withheld under NDA.

Keep reading

More from on call

View all posts
A server-rack door ajar with a key left in the lock — when a tool call becomes a shell: authenticated RCE via an AI agent tool
case-studiesOct 18, 2026

Authenticated RCE through an AI agent's execute tool

During a real penetration test, any signed-in member could get a product's built-in AI assistant to run shell commands on the server — not through an exploit chain, but by asking. The model's refusal to run 'sensitive' commands looked like a control. It wasn't.

A hand throwing a KILL SWITCH lever — know the thread ID, kill the run: an unauthenticated agent/stop with no ownership check
case-studiesOct 18, 2026

When one endpoint method forgets the authorization check

The smallest finding from this engagement, and the most ordinary — the kind of bug that predates AI entirely. One method on the chat endpoint checked who was asking. Another, right next to it, didn't.

A tall stack of CVE reports beside one flagged page — 200 CVEs, five that matter: real risk scoring through one MCP server
productOct 17, 2026

CVE MCP: 41 tools, 11 sources, real risk scoring

A scan drops 200 CVEs on your desk. CVSS alone can't tell you which five matter. cve-mcp pulls severity, exploitation probability, active-exploitation status and weaponization into one MCP server, and scores what's actually urgent.

Get the next post in your inbox

One email a month with new posts, product updates and the odd postmortem worth reading. Unsubscribe in one click.