CVE-2026-107289: Pydantic AI: SSRF cloud-metadata blocklist bypass via IPv6 zone identifier (incomplete fix for CVE-2026-46678 and CVE-2026-48782)
Summary
When an application using Pydantic AI opts a URL into local network access — either a FileUrl with forcedownload='allow-local', or webfetchtool(allowlocalurls=True) — the cloud-metadata blocklist could be bypassed by appending an IPv6 zone identifier to a metadata address (for example fd00:ec2::254%251). The host ignores the zone identifier on a destination that is not link-local and delivers the request to the metadata endpoint anyway, exposing cloud IAM short-term credentials.
This is an incomplete fix of GHSA-cqp8-fcvh-x7r3 / CVE-2026-46678 and GHSA-cg7w-rg45-pc59 / CVE-2026-48782, themselves follow-ups to CVE-2026-25580. The parent advisory's remediation guaranteed that cloud metadata endpoints are always blocked, even with local access allowed. That guarantee did not hold for zone-scoped spellings of the IPv6 metadata endpoints.
Details
The cloud-metadata guard compared IPv6 addresses against its blocklist by set membership. Python includes the zone identifier in IPv6Address equality and hashing, so a zone-scoped spelling of a blocked address did not match, while the network stack ignores the zone identifier for a destination that is not link-local. The private-range checks, and the IPv4 and transition-form metadata checks, were already unaffected, because they compare by network containment and by packed bytes respectively.
Only the IPv6 cloud metadata endpoints were reachable this way, so the issue requires an IPv6-enabled environment — for example AWS EC2 or EKS with IPv6, GCP IPv6-only instances, or Scaleway.
Who Is Affected
You are affected only if your application opts a URL that is, or could be, influenced by untrusted input into local network access, through either:
- a FileUrl (ImageUrl, AudioUrl, VideoUrl, DocumentUrl) with forcedownload='allow-local'; or - webfetchtool(allowlocalurls=True), where the model chooses the URL.
Both are off by default.
You are not affected through the FileUrl path if you use any of the bundled integrations to ingest user input, because they do not propagate forcedownload from external data:
- Agent.toweb / clai web - VercelAIAdapter - AGUIAdapter / Agent.toagui
webfetchtool is configured by your own application, so a client cannot turn on allowlocalurls.
Applications that only download from developer-controlled URLs are not affected.
Remediation
Upgrade to a patched version. The cloud-metadata and private-IP checks now drop an IPv6 zone identifier before evaluating the address, so every blocklist comparison is made on the address itself. A zone identifier is still carried on the connection, so legitimate link-local fetches under local network access continue to work.
Workaround for Unpatched Versions
Avoid opting into local network access — forcedownload='allow-local' or webfetchtool(allowlocalurls=True) — on any URL that could be influenced by untrusted input. If you must, reject URL hosts containing % before constructing the FileUrl or configuring the tool.
Credits
Reported by @euriconicacio.
Other sources
Pydantic AI is a Python agent framework for building applications and workflows with Generative AI. From 1.56.0 until 1.107.6 and 2.44.0, applications that opt attacker-influenced URLs into local network access through FileUrl with forcedownload='allow-local' or webfetchtool with allowlocalurls=True can bypass the cloud-metadata blocklist by appending an IPv6 zone identifier to an IPv6 metadata address. IPv6Address equality and hashing include the zone identifier, so the blocklist comparison fails even though the network stack ignores the zone on a non-link-local destination and reaches the metadata service, potentially exposing cloud IAM credentials. The opt-in settings are disabled by default, and the issue requires an IPv6-enabled environment. This issue is fixed in versions 1.107.6 and 2.44.0.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/pydantic-ai-slimto a version that resolves this vulnerability.Fixed in 2.44.0 - Upgrade
Upgrade
pip/pydantic-ai-slimto a version that resolves this vulnerability.Fixed in 1.107.6 - Upgrade
Upgrade
pip/pydantic-aito a version that resolves this vulnerability.Fixed in 2.44.0 - Upgrade
Upgrade
pip/pydantic-aito a version that resolves this vulnerability.Fixed in 1.107.6 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 1.107.6 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 2.44.0 - Configuration
Avoid opting into local network access: do not use force_download='allow-local' or configure web_fetch_tool with allow_local_urls=True for URLs that could be influenced by untrusted input.
Pydantic AI local network access force_download / allow_local_urls = disabled - Compensating control
Reject URL hosts containing '%' before constructing a FileUrl or configuring the web_fetch_tool.
Event History
Frequently Asked Questions
Which deployments are exposed?
Applications using Pydantic AI versions from 1.56.0 up to 1.107.6, or version 2.44.0, are exposed only when they permit attacker-influenced URLs to access local networks through FileUrl with force_download='allow-local' or web_fetch_tool with allow_local_urls=True. The environment must also have IPv6 enabled.
Are default configurations affected?
No. The relevant local-network URL access settings are disabled by default; exposure requires explicitly enabling one of them.
What does an attacker need to exploit this issue?
An attacker needs to influence a URL processed by the affected FileUrl or web_fetch_tool configuration. They can append an IPv6 zone identifier to an IPv6 cloud-metadata address, causing the blocklist comparison to fail while the network stack still reaches the metadata service.
What is the potential impact?
Successful exploitation can allow access to a cloud metadata service and potentially expose cloud IAM credentials. Integrity and availability impacts are not described.
How can the issue be remediated if the application needs local URL access?
Upgrade to Pydantic AI 1.107.6 or 2.44.0. If upgrading is not immediately possible, do not enable force_download='allow-local' or allow_local_urls=True for attacker-influenced URLs.