Open-Source Security Intelligence

Know every vulnerability
before it knows you.

DevGuard continuously monitors your dependencies and alerts you when CVEs like this one affect your stack — with real-time threat intelligence built for developers.

Search

GHSA-vg6p-v9vm-6fgj

HighCVSS 7.5 / 10
Published Aug 25, 2026·Last modified Aug 25, 2026
Affected Components(1)
PyPI logopraisonaiagents
< 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.

Upload your SBOM

Upload your own SBOM in CycloneDX 1.6 or higher (JSON) directly here to check your vulnerabilities.

Risk Scores
Base Score
7.5

The vulnerability can be exploited over the network without needing physical access. It is difficult for an attacker to exploit this vulnerability and may require special conditions. An attacker does not need any special privileges or access rights. No user interaction is needed for the attacker to exploit this vulnerability. The vulnerability can affect other systems as well, not just the initial system. There is a high impact on the confidentiality of the information. There is a low impact on the integrity of the data.

Threat Intelligence
6.9

Exploitation attempts have been detected. Elevated vigilance and prompt remediation are advised.

EPSS
N/A

Probability that this vulnerability will be exploited in the wild within the next 30 days.

Exploit
Not available

We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database.

Related Vulnerabilities
  • CVE-2026-55524
    Alias
  • EUVD-2026-53606
    Alias

Browse More

Scan your project

Continuously monitor your dependencies and get alerted when vulnerabilities like this one affect your stack.

Checkout DevGuard