# SSRF Redirect Bypass in Agent Scraping Fetch

- **Severity:** High
- **Signature ID:** `3f1c9a6e-8d24-4b71-9c53-2a7e5b0d61f4`

## Summary

An AI agent that fetches web pages can be tricked into visiting internal, non-public addresses. This happens when an attacker's public URL responds with an HTTP redirect pointing at an internal host, and the agent follows it without re-checking whether that new destination is allowed.

## How the attack works

The agent is given or fetches an attacker-controlled public URL as part of a normal scraping task. That URL responds with an HTTP redirect (301/302/303/307/308) instead of content. The agent follows the redirect and issues a request to an internal address - a private IP range, loopback, link-local address, cloud metadata endpoint (like 169.254.169.254), or an internal-style hostname. Because the agent's security allowlist was checked against the original public URL and not the redirect target, the internal request goes through even though it would normally be blocked. This affects CrewAI versions before 1.15.1a1.

## Why it matters

An attacker can use a public-facing scraping task to make an AI agent reach internal services it should never touch - including cloud metadata endpoints that often hand out temporary credentials - potentially leading to internal network reconnaissance or credential theft.

## What you can do

- Upgrade CrewAI (or any agent framework with this fetch pattern) to a version that re-validates redirect targets against the SSRF allowlist before following them.
- Configure agents to not follow redirects automatically, or to require a fresh allowlist check on every redirect hop.
- Block agent processes from reaching link-local addresses (especially 169.254.169.254) and RFC1918 ranges unless explicitly required.
- Review logs for agent fetches that start at a public URL, receive a 3xx response, and are quickly followed by a request to an internal address the agent rarely or never contacts.

## Known benign look-alikes

- Agent scrapes an external corporate link that legitimately 302s to an intranet portal or SSO host reachable over the private tunnel. Mitigated by the fetch-count cap (a genuinely used internal portal quickly exceeds 3 fetches and stops matching) and by the 10-minute per-(public,internal) suppression window.
- Local development proxy, MCP gateway or model server on 127.0.0.1 receiving its first one or two requests just after an unrelated external GET. Mitigated by the fetch-count cap and by requiring a 3xx response recorded on the public host.
- Cloud SDK IMDS credential refresh (169.254.169.254) happening to land within 15s of an external fetch that returned a redirect. Mitigated by the same fetch-count cap - only the first few metadata fetches of a session can match - and by report, not block.
- Link-shortener / CDN redirect chains whose final hop is a split-horizon single-label hostname. This is genuinely indistinguishable from the attack at the network layer and is the intended reason this rule reports rather than blocks.
- Kubernetes in-cluster service fetch (svc / cluster.local) by an agent that also scrapes the public internet in the same task.

## References

- https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/
- https://github.com/crewAIInc/crewAI/releases

---
Source: https://www.netzilo.com/threats/ssrf-redirect-bypass-chain
