TL;DR

Python's urllib.parse.urlparse treats a backslash inside the authority as an ordinary character, so a URL built to show one host to the parser connects to another through urllib3. An SSRF guard that validates the parsed host and then hands the raw string to requests is bypassed. Two agent frameworks had that guard: CrewAI (crewai-tools, validate_url in security/safe_path.py, reachable through ScrapeWebsiteTool from a URL the model chooses; CERT/CC's CVE-2026-120630, published 2026-11-02, affected before 1.15.17, fixed on PyPI 2026-08-20) and Langflow (IBM's CVE-2026-19304, CVSS 7.7, 1.0.0 through 1.11.2, RSSReaderSimple and SearXNGToolComponent, fixed 1.11.3 on 2026-08-11). Both fixes are three months old; the CrewAI record is the new fact. Upgrade both packages, and if you wrote your own urlparse-then-requests allowlist, assume it has the same hole.

What happened

The research. A September 2026 write-up on badcast.dev ("parser differential SSRF in AI agents", 2026-09-05, GitHub user sushrut1058) reports a URL whose authority contains a backslash: urlparse reports the public hostname before the backslash while urllib3 connects to the address after it. The author tested the parser behaviour on Python 3.11, 3.12 and 3.13 and found two frameworks whose SSRF guards validated the urlparse host and then fetched the raw string. The timeline in the post: Langflow reported 2026-08-01 via HackerOne, fix merged 2026-08-07, CVE assigned 2026-09-02; CrewAI reported 2026-08-02 via Bugcrowd, fix merged 2026-08-17; both triaged 2026-08-05, both "vendor confirmed" 2026-08-28; "Both vendors shipped fixes within two weeks of receiving the report". The post expected the CrewAI id "via GitHub Security Advisory" and it arrived instead from CERT/CC.

CrewAI, CVE-2026-120630. The CERT/CC record (published 2026-11-02 17:37 UTC, no CVSS) lists product "CrewAI" affected from 0 before 1.15.17 and describes "an SSRF vulnerability caused by its SSRF guard and HTTP client, which both miss malicious content in URLs by checking opposite content passed to it, enabling any request that injects a malicious URL to perform SSRF, such as with the ScrapWebsiteTool" (the record's spelling). Its references are the ScrapeWebsiteTool documentation at 1.15.16, the badcast post and pull request 6981. That PR, "fix(tools): pin SSRF fetches to the validated peer IP", merged into main on 2026-08-17; its description says validate_url checked only the original URL string while requests.get resolved DNS again at connect time, and the fix pins each fetch to the validated socket address, rejects proxy settings unless an escape hatch is set, and adds CREWAI_TOOLS_FORCE_SAFE_PATHS. The PR carries no CVE and no release number. PyPI published crewai-tools 1.15.17 and crewai 1.15.17 together on 2026-08-20; pip index versions shows 1.15.34 as newest on 2026-11-03. The CNA names the product "CrewAI"; the code the researcher and the PR name is in crewai-tools, and the two packages share version numbers, so "before 1.15.17" applies to both. The GitHub Advisory Database row (GHSA-x35j-64g3-fxg7, 2026-11-02) is unreviewed with no package metadata, so pip-audit will not flag it until a reviewer adds the range. This is the fourth SSRF id on CrewAI's tools in 2026 after CVE-2026-2286 (RAG search tools, March), CVE-2026-62240 (redirect and DNS-rebinding bypass, fixed 1.15.1) and CVE-2026-112308 (through 1.15.28, unmerged fix) in the CrewAI file; the vendor's security tab is still empty.

Langflow, CVE-2026-19304 and three siblings. IBM's bulletin 7285639 (published 2026-08-28, modified 2026-09-28) covers four SSRF CVEs in Langflow OSS "1.0.0-1.11.2", all fixed in 1.11.3: CVE-2026-19304 (7.7, AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N), "a URL parser discrepancy involving backslashes, so validation passes for a public hostname while the request reaches a private address" in RSSReaderSimple and SearXNGToolComponent; CVE-2026-19305 (8.6, unauthenticated), the LMStudio model and embeddings components passing a user-controlled base URL to the HTTP client with no SSRF validation; CVE-2026-19301 (5.0), OpenAI-compatible model discovery sending server-side GETs to a user-controlled base URL with redirects enabled; and CVE-2026-12766 (5.4), the SQL Database connector checking only the URL hostname while SQLAlchemy dialect query parameters override host and port. The CVE record for CVE-2026-19304 (IBM CNA, 2026-09-04) matches the bulletin. The fix is pull request 14430, "fix(security): reject ambiguous URL authorities", merged into release-1.11.3 on 2026-08-07, which rejects raw authorities containing a backslash before any validator or client sees them; PyPI published 1.11.3 on 2026-08-11. None of the four ids was in this corpus before this file; the IBM bulletins tracked here start at the September eleven-CVE batch, and every later Langflow release (1.12.4, 1.12.5, 1.13.0) carries this fix.

The class. A guard that parses a URL with one library and fetches with another is a parser differential. The two fixes differ: Langflow rejects ambiguous input; CrewAI pins the connection to the address it validated. The second is the stronger pattern because it also closes DNS rebinding, which the first does not.

Am I affected?

pip show crewai-tools crewai 2>/dev/null | grep -E '^(Name|Version)'   # both < 1.15.17: affected
pip show langflow 2>/dev/null | grep -E '^Version'                      # 1.0.0 to 1.11.2: affected by all four
  • CrewAI: any crew whose tools fetch a URL the model chooses (ScrapeWebsiteTool, the RAG loaders, url_read_tool) on crewai-tools below 1.15.17. The guard existed, so a scanner that keys on "has an SSRF guard" reads clean.
  • Langflow: any 1.0.0 to 1.11.2 instance where a user, or a flow fed by untrusted input, can set an RSS, SearXNG, LMStudio or OpenAI-compatible base URL, or a SQL connection string. CVE-2026-19305 needs no login.
  • Your own code: grep for urlparse( next to requests.get( or urllib3 in anything that allowlists hosts.

If you are affected

  • Upgrade crewai-tools and crewai to 1.15.17 or later (1.15.34 is current) and Langflow to 1.11.3 or later (1.13.0 is current, and 1.12.4 or 1.12.5 are the minimums for the October bulletins).
  • If the instance could reach cloud metadata (169.254.169.254) or internal services, rotate the credentials those endpoints hand out and review their access logs since August. See rotating cloud credentials and if your local AI agent was exploited.

Prevention

  • Resolve the host once, validate the resolved address, and connect to that address, as CrewAI's fix does. Validation of a string the client will re-parse is not validation.
  • Run agent frameworks with no route to metadata endpoints and internal networks. See agent sandboxing and MCP hygiene.

Sources