Skip to content

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

High severity GitHub Reviewed Published Jun 13, 2026 in MervinPraison/PraisonAI • Updated Aug 25, 2026

Package

pip praisonaiagents (pip)

Affected versions

< 1.6.58

Patched versions

1.6.58

Description

The web_crawl tool performs its SSRF check only on the initial URL: it resolves the hostname once
with socket.gethostbyname and rejects private/loopback/link-local results. It then passes the URL to
a fetcher that uses httpx.Client(follow_redirects=True) - or urllib.request.urlopen when httpx is
absent, which also follows redirects - and re-resolves the hostname at connect time, with no further
validation. This validate-here/fetch-there gap is bypassable two independent ways: HTTP redirects and
DNS rebinding.

Affected code: src/praisonai-agents/praisonaiagents/tools/web_crawl_tools.py

  • Single-shot validation (lines 229-238):
    if os.environ.get("ALLOW_LOCAL_CRAWL") != "true":
    ip_str = socket.gethostbyname(hostname) # resolved ONCE, at validation time
    ip = ipaddress.ip_address(ip_str)
    if ip.is_loopback or ip.is_private or ip.is_link_local or ip.is_multicast or ip.is_unspecified:
    continue # rejected
    url_list.append(u)
  • Vulnerable fetch (_crawl_with_httpx, lines 142 / 149): follows redirects, re-resolves DNS, no re-check:
    with httpx.Client(follow_redirects=True, timeout=30.0) as client: response = client.get(url)

    fallback: urllib.request.urlopen(url, timeout=30) (also follows redirects by default)

  • web_crawl / crawl_web are registered tools (tools/init.py:156-157); httpx is the default fallback
    provider (dispatch at web_crawl_tools.py:269).

The two bypasses:

  1. Redirect: validation approves an attacker domain resolving to a public IP; attacker server replies
    302 Location: http://169.254.169.254/... (or any internal host); the fetcher follows it unchecked.
  2. DNS rebinding (TOCTOU): validator's gethostbyname and fetcher's connect-time resolution are
    independent; a low-TTL attacker domain answers public to the validator and private/loopback to fetch.

Impact:
An agent with web_crawl - driven by direct input or indirect prompt injection - can be made to read
internal-only HTTP services and cloud instance-metadata endpoints (e.g. IAM credentials), with the
response body returned in the tool output. Scope is Changed because the request pivots into the
internal network.

Proof of concept:
A PoC drives the real web_crawl() (httpx absent -> genuine urllib fallback). It runs a loopback
"internal metadata" service and a loopback attacker redirector, substituting DNS only to stand in
for "attacker owns a public domain" / offline routing - the redirect-following and connect-time
re-resolution are the repo's own behavior. Observed:
CONTROL: web_crawl("http://127.0.0.1:.../meta-data/") -> blocked (validator works)
PoC 1A (redirect): attacker.example approved (public); 302 -> loopback metadata
-> result.content leaks {"AccessKeyId":"ASIA_FAKE_STOLEN_CREDENTIAL_..."}
PoC 1B (rebinding): gethostbyname(rebind.example)->public (allowed); connect->127.0.0.1
-> same secret leaked
The control proves the validator blocks a direct loopback request, so the bypasses are genuine.

Remediation:
Resolve the hostname once, validate that IP, and connect to that exact validated IP (pin it) rather
than re-resolving. Disable redirect following (follow_redirects=False; for urllib use a redirect
handler that re-validates), or re-validate every redirect hop's resolved IP. Apply the deny check to
both the validator and the actual socket target. file_tools.py:364 already uses follow_redirects=False
and is the correct pattern to propagate.

Distinct from prior advisories:
The accepted SSRF advisories concern host-string parsing in different code — alternate loopback
encodings in spider_tools (GHSA-5c6w-wwfq-7qqm) and the CLI @url feature (GHSA-5cxw-77wg-jrf3). This
is in the web_crawl tool, which neither advisory names, and the mechanisms (redirect-following and DNS
rebinding) differ categorically from host-string encoding; the spider_tools _host_is_blocked hardening
does not apply to this tool.

References

@MervinPraison MervinPraison published to MervinPraison/PraisonAI Jun 13, 2026
Published by the National Vulnerability Database Aug 5, 2026
Published to the GitHub Advisory Database Aug 25, 2026
Reviewed Aug 25, 2026
Last updated Aug 25, 2026

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
High
Privileges required
None
User interaction
None
Scope
Changed
Confidentiality
High
Integrity
Low
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N

EPSS score

Exploit Prediction Scoring System (EPSS)

This score estimates the probability of this vulnerability being exploited within the next 30 days. Data provided by FIRST.
(9th percentile)

Weaknesses

Time-of-check Time-of-use (TOCTOU) Race Condition

The product checks the state of a resource before using that resource, but the resource's state can change between the check and the use in a way that invalidates the results of the check. Learn more on MITRE.

Server-Side Request Forgery (SSRF)

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination. Learn more on MITRE.

CVE ID

CVE-2026-55524

GHSA ID

GHSA-vg6p-v9vm-6fgj

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.