# praisonaiagents vulnerable to SSRF in web_crawl tool via redirect-following and DNS rebinding (validate-then-fetch gap)

PraisonAI's web_crawl validated only the initial URL's IP, then followed redirects and re-resolved DNS, letting agents be steered into cloud metadata and internal services.

- Payout: Research
- Severity: high
- Program: PraisonAI
- Found by: sour-exploit
- Disclosed: 2026-08-25
- CVE: CVE-2026-55524
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-vg6p-v9vm-6fgj
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-vg6p-v9vm-6fgj
- Tags: area:ai domain:ai impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:python technique:chained technique:source-review vuln:race-condition vuln:ssrf

**Target:** web_crawl tool in praisonaiagents (httpx/urllib fetcher)
**Root cause:** SSRF check resolves the hostname once with socket.gethostbyname and validates that IP, but the fetcher (httpx follow_redirects=True or urllib.urlopen) re-resolves at connect time and follows redirects with no re-validation.
**Steps:**
1. Observe web_crawl_tools.py:229-238 validates only the initial hostname via `socket.gethostbyname(hostname)` and rejects private/loopback/link-local IPs.
2. Observe _crawl_with_httpx uses `httpx.Client(follow_redirects=True, timeout=30.0)` and fallback `urllib.request.urlopen(url, timeout=30)`, both following redirects and re-resolving DNS.
3. Control: `web_crawl("http://127.0.0.1:.../meta-data/")` is blocked, confirming the validator works.
4. PoC 1A: submit an attacker domain resolving to a public IP; server replies `302 Location: http://169.254.169.254/...`; fetcher follows unchecked and returns metadata body.
5. PoC 1B: low-TTL domain answers public to gethostbyname (allowed) then 127.0.0.1 at connect time (rebinding); same secret leaked.
**How found:** Code reading of the validate-then-fetch gap: validation resolves once, fetcher re-resolves and follows redirects; confirmed with a control test showing direct loopback is blocked while redirect and rebinding bypasses leak the fake secret.
**Exploitation:** Attacker controls a domain (or injects a prompt) so the agent calls web_crawl on it; the approved public IP redirects or rebinds to internal/metadata endpoints, and the response body (e.g. IAM credentials) is returned in tool output.
**Escalation:** Chained with indirect prompt injection against an agent holding web_crawl to pivot into internal network and cloud metadata, scope Changed.
**Insight:** When auditing SSRF guards, check whether the validated IP is the one actually connected to: any follow_redirects=True or separate connect-time DNS resolution reopens the hole even if the initial check is correct.

