GitHub Advisoryadvisory · PyPI

GHSA-6g59-gm2v-qhvq PraisonAI: Crawl4AI/Chromium backend is also affected by the `web_crawl` SSRF validation bypass

HIGH Published 2026-10-07 Modified 2026-10-07 Official page ↗
Aliases
CVE-2026-61429
Ecosystem
PyPI
Packages
praisonaiagents
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Weaknesses
CWE-200, CWE-367, CWE-918
Reviewed
2026-10-07

Affected packages

• PyPI praisonaiagents: < 1.6.78 → fixed in 1.6.78

Description

Summary The DNS-rebinding / redirect SSRF bypass in PRAI-05 is not limited to the httpx/urllib backend. When `crawl4ai` (headless Chromium via Playwright) is installed, `web_crawl` auto-selects `provider=crawl4ai`, and the headless browser re-resolves DNS and follows redirects on its own — with no per-connection SSRF guard. Runtime-confirmed read-back of the internal canary via both DNS rebinding and redirect (`provider: "crawl4ai"`). Status: runtime-confirmed addendum to PRAI-05. Details Affected component • Package `praisonaiagents` 4.6.63. Backend selected when `crawl4ai`+Playwright are installed. • Files: `src/praisonai-agents/praisonaiagents/tools/web_crawl_tools.py` (`_crawl_with_crawl4ai`) and `src/praisonai-agents/praisonaiagents/tools/crawl4ai_tools.py` (standalone crawl wrappers). Vulnerable code / root cause Path: `src/praisonai-agents/praisonaiagents/tools/web_crawl_tools.py` Function: `_crawl_with_crawl4ai` Snippet: ```python async with AsyncWebCrawler() as crawler: for url in urls: result = await crawler.arun(url=url) # headless browser: re-resolves DNS, follows redirects ``` Path: `src/praisonai-agents/praisonaiagents/tools/crawl4ai_tools.py` Function: `Crawl4AITools.crawl` / `crawl4ai` Snippet: ```python result = await crawler.arun(url=url, config=config) # no _is_safe_crawl_url / no per-connect validation ``` Issue: the only SSRF check is the single pre-fetch `_is_safe_crawl_url()` on the initial URL string in `web_crawl()` (see PRAI-05). The headless browser then resolves and connects independently and follows redirects in-browser — no resolved-IP pinning, no per-hop/per-connect validation. Input (`urls`) is attacker/agent-controlled; the sink is `crawler.arun(url=...)`; the guard is bypassed by DNS rebinding (TOCTOU) and by redirects (followed in-browser). Attack flow / Why bypassed / Security boundary Identical to PRAI-05: TOCTOU between the guard's resolution and the browser's connection; redirects followed in-browser; internal response returned as crawl `content`. See PRAI-05. Proof of Concept Environment `crawl4ai` + Playwright Chromium installed in a dedicated runtime container (`127.0.0.1:18081`), same controlled internal canary + rebinding DNS. Runnable assets: `PraisonAI-Runtime-Repro\runtime-files\` (`docker-compose.crawl.yml`). Steps to reproduce 1. `SSRF-04-01-Crawl4AI-DNS-Rebind-Trigger` → `127.0.0.1:18081`: ```http POST /tool/web_crawl HTTP/1.1 Host: 127.0.0.1:18081 Content-Type: application/json {"url":"http://rebind.lab:8081/secret"} ``` 2. Redirect variant `SSRF-04-03-Crawl4AI-Redirect-Readback`: `{"url":"http://redirector:8082/redirect-to-internal"}`. Expected result The crawl backend refuses internal destinations regardless of DNS timing/redirects. Actual result HTTP 200, `"provider":"crawl4ai"`, response `content` contains `PRAISONAI_INTERNAL_SECRET_CANARY_7f3a91` + `FAKE_INTERNAL_TOKEN_DO_NOT_USE_7f3a91` for both the DNS-rebinding and the redirect payload. Screenshots Crawl4AI DNS rebinding read-back The attacker-controlled `rebind.lab` URL is accepted by the Crawl4AI-backed `web_crawl` endpoint. PraisonAI returns the internal canary response body containing `PRAISONAI_INTERNAL_SECRET_CANARY_7f3a91`. Crawl4AI DNS rebinding runtime evidence The runtime log shows the Crawl4AI/Chromium backend resolving `rebind.lab` to an internal Docker IP during the fetch phase. The internal canary receives `GET /secret` from a headless Chrome user agent. Crawl4AI redirect read-back The attacker-controlled redirector URL is accepted by the Crawl4AI-backed endpoint. PraisonAI follows the redirect and returns the internal canary response body. Crawl4AI redirect runtime evidence The controlled redirector returns `302 -> http://internal-canary:8081/secret`, and the internal canary receives `GET /secret` from the Crawl4AI/Chromium backend. Impact Same class as PRAI-05: read-back SSRF to internal/metadata services, now on the crawl4ai backend. Broadens the affected surface (the flaw is in the shared validate-without-pinning design, not one backend). Suggested remediation Resolve-once + IP-pin + per-connect validation must also cover the crawl4ai backend (constrain the headless browser to the validated IP, or allowlist crawl destinations).

Related

Alias · CVE (1)

  • CVE-2026-61429 PraisonAI versions before 1.6.78 contain a server-side request forgery vulnerability in the Crawl4AI/Chromium backend that allows attackers… vulnerability

Weakness · CWE (3)

  • CWE-200 Exposure of Sensitive Information to an Unauthorized Actor weakness
  • CWE-367 Time-of-check Time-of-use (TOCTOU) Race Condition weakness
  • CWE-918 Server-Side Request Forgery weakness

References