{"id":"CVE-2026-48782","aliases":["EUVD-2026-37512","GHSA-cg7w-rg45-pc59","PYSEC-2026-2977","PYSEC-2026-2981","ROOT-APP-PYPI-CVE-2026-48782"],"status":"published","title":"pydantic-ai: SSRF blocklist bypass via IPv4-compatible, SIIT/IVI, and local NAT64 IPv6 addresses (incomplete fix of CVE-2026-46678)","description":"Pydantic AI is a Python agent framework for building applications and workflows with Generative AI. In versions 1.56.0 through 1.101.0, 2.0.0b1, and 2.0.0b2, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix, CVE-2026-46678, did not decode, exposing cloud IAM short-term credentials. The previous remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix, so the metadata guarantee did not hold for the remaining transition forms: IPv4-compatible IPv6 (::a.b.c.d), the NAT64 RFC 8215 local-use prefix (64:ff9b:1::/48), operator-chosen NAT64 prefixes, and ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint. This occurs when an application using Pydantic AI opts a URL into force_download='allow-local' (which disables the default block on private/internal IPs) and runs on a network that actually routes the affected IPv6 transition forms: NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route these forms and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth. This is an incomplete fix of GHSA-cqp8-fcvh-x7r3 / CVE-2026-46678 (itself a follow-up to CVE-2026-25580). This issue has been fixed in version 2.0.0b3.","severity":{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00401,"percentile":0.34771,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-918"],"published":"2026-06-16T22:49:26Z","modified":"2026-10-28T02:30:57Z","fixes":[{"ecosystem":"PyPI","package":"pydantic-ai-slim","fixed_in":["1.102.0","2.0.0b3"],"sources":["ghsa","osv"]},{"ecosystem":"PyPI","package":"pydantic-ai","fixed_in":["1.102.0","2.0.0b3"],"sources":["ghsa","osv"]},{"ecosystem":"Root:PyPI","package":"pydantic-ai-slim","fixed_in":["1.84.0+aikido.2","1.88.0+aikido.2","1.84.1+aikido.2","1.91.0+aikido.2"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"pydantic-ai-slim","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.56.0"},{"fixed":"1.102.0"}]}]},{"source":"ghsa","ecosystem":"PyPI","package":"pydantic-ai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.56.0"},{"fixed":"1.102.0"}]}]},{"source":"ghsa","ecosystem":"PyPI","package":"pydantic-ai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0b1"},{"fixed":"2.0.0b3"}]}]},{"source":"ghsa","ecosystem":"PyPI","package":"pydantic-ai-slim","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0b1"},{"fixed":"2.0.0b3"}]}]},{"source":"osv","ecosystem":"PyPI","package":"pydantic-ai-slim","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.56.0"},{"fixed":"1.102.0"}]}],"versions":["1.100.0","1.101.0","1.56.0","1.57.0","1.58.0","1.59.0","1.60.0","1.61.0","1.62.0","1.63.0","1.64.0","1.65.0","1.66.0","1.67.0","1.68.0","1.69.0","1.70.0","1.71.0","1.72.0","1.73.0","1.74.0","1.75.0","1.76.0","1.77.0","1.78.0","1.79.0","1.80.0","1.81.0","1.82.0","1.83.0","1.84.0","1.84.1","1.85.0","1.85.1","1.86.0","1.86.1","1.87.0","1.88.0","1.89.0","1.89.1","1.90.0","1.91.0","1.92.0","1.93.0","1.94.0","1.95.0","1.95.1","1.96.0","1.96.1","1.97.0","1.98.0","1.99.0"]},{"source":"osv","ecosystem":"PyPI","package":"pydantic-ai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.56.0"},{"fixed":"1.102.0"}]}],"versions":["1.100.0","1.101.0","1.56.0","1.57.0","1.58.0","1.59.0","1.60.0","1.61.0","1.62.0","1.63.0","1.64.0","1.65.0","1.66.0","1.67.0","1.68.0","1.69.0","1.70.0","1.71.0","1.72.0","1.73.0","1.74.0","1.75.0","1.76.0","1.77.0","1.78.0","1.79.0","1.80.0","1.81.0","1.82.0","1.83.0","1.84.0","1.84.1","1.85.0","1.85.1","1.86.0","1.86.1","1.87.0","1.88.0","1.89.0","1.89.1","1.90.0","1.91.0","1.92.0","1.93.0","1.94.0","1.95.0","1.95.1","1.96.0","1.96.1","1.97.0","1.98.0","1.99.0"]},{"source":"osv","ecosystem":"PyPI","package":"pydantic-ai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0b1"},{"fixed":"2.0.0b3"}]}],"versions":["2.0.0b1","2.0.0b2"]},{"source":"osv","ecosystem":"PyPI","package":"pydantic-ai-slim","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0b1"},{"fixed":"2.0.0b3"}]}],"versions":["2.0.0b1","2.0.0b2"]},{"source":"osv","ecosystem":"PyPI","package":"pydantic-ai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.56.0"},{"fixed":"1.102.0"},{"introduced":"2.0.0b1"},{"fixed":"2.0.0b3"}]}],"versions":["1.100.0","1.101.0","1.56.0","1.57.0","1.58.0","1.59.0","1.60.0","1.61.0","1.62.0","1.63.0","1.64.0","1.65.0","1.66.0","1.67.0","1.68.0","1.69.0","1.70.0","1.71.0","1.72.0","1.73.0","1.74.0","1.75.0","1.76.0","1.77.0","1.78.0","1.79.0","1.80.0","1.81.0","1.82.0","1.83.0","1.84.0","1.84.1","1.85.0","1.85.1","1.86.0","1.86.1","1.87.0","1.88.0","1.89.0","1.89.1","1.90.0","1.91.0","1.92.0","1.93.0","1.94.0","1.95.0","1.95.1","1.96.0","1.96.1","1.97.0","1.98.0","1.99.0","2.0.0b1","2.0.0b2"]},{"source":"osv","ecosystem":"PyPI","package":"pydantic-ai-slim","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.56.0"},{"fixed":"1.102.0"},{"introduced":"2.0.0b1"},{"fixed":"2.0.0b3"}]}],"versions":["1.100.0","1.101.0","1.56.0","1.57.0","1.58.0","1.59.0","1.60.0","1.61.0","1.62.0","1.63.0","1.64.0","1.65.0","1.66.0","1.67.0","1.68.0","1.69.0","1.70.0","1.71.0","1.72.0","1.73.0","1.74.0","1.75.0","1.76.0","1.77.0","1.78.0","1.79.0","1.80.0","1.81.0","1.82.0","1.83.0","1.84.0","1.84.1","1.85.0","1.85.1","1.86.0","1.86.1","1.87.0","1.88.0","1.89.0","1.89.1","1.90.0","1.91.0","1.92.0","1.93.0","1.94.0","1.95.0","1.95.1","1.96.0","1.96.1","1.97.0","1.98.0","1.99.0","2.0.0b1","2.0.0b2"]},{"source":"osv","ecosystem":"Root:PyPI","package":"pydantic-ai-slim","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.84.0+aikido.2"},{"fixed":"1.88.0+aikido.2"},{"fixed":"1.84.1+aikido.2"},{"fixed":"1.91.0+aikido.2"}]}]}],"products":[{"vendor":"pydantic","product":"pydantic-ai"},{"vendor":"pydantic","product":"pydantic-ai-slim"},{"vendor":"pydantic","product":"pydantic_ai"}],"references":[{"url":"https://github.com/pydantic/pydantic-ai/security/advisories/GHSA-cg7w-rg45-pc59","tags":["x_refsource_CONFIRM","Vendor Advisory","advisory","web"]},{"url":"https://github.com/pydantic/pydantic-ai/pull/5596","tags":["x_refsource_MISC","Issue Tracking","Patch","fix","web"]},{"url":"https://github.com/pydantic/pydantic-ai/commit/1add06179ba4de259f7ab977620b697b7209f7e4","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/pydantic/pydantic-ai/releases/tag/v1.102.0","tags":["x_refsource_MISC","Product","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-48782","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-cg7w-rg45-pc59","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/48xxx/CVE-2026-48782.json","tags":["advisory"]},{"url":"https://github.com/pydantic/pydantic-ai","tags":["package"]},{"url":"https://pypi.org/project/pydantic-ai","tags":["package"]},{"url":"https://pypi.org/project/pydantic-ai-slim","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-48782","title":"pydantic-ai: SSRF blocklist bypass via IPv4-compatible, SIIT/IVI, and local NAT64 IPv6 addresses (incomplete fix of CVE-2026-46678)","description":"Pydantic AI is a Python agent framework for building applications and workflows with Generative AI. In versions 1.56.0 through 1.101.0, 2.0.0b1, and 2.0.0b2, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix, CVE-2026-46678, did not decode, exposing cloud IAM short-term credentials. The previous remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix, so the metadata guarantee did not hold for the remaining transition forms: IPv4-compatible IPv6 (::a.b.c.d), the NAT64 RFC 8215 local-use prefix (64:ff9b:1::/48), operator-chosen NAT64 prefixes, and ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint. This occurs when an application using Pydantic AI opts a URL into force_download='allow-local' (which disables the default block on private/internal IPs) and runs on a network that actually routes the affected IPv6 transition forms: NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route these forms and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth. This is an incomplete fix of GHSA-cqp8-fcvh-x7r3 / CVE-2026-46678 (itself a follow-up to CVE-2026-25580). This issue has been fixed in version 2.0.0b3.","status":"published","published":"2026-06-16T22:49:26.75Z","modified":"2026-06-17T14:22:48.236Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T13:50:49.872037Z"}],"euvd":[{"id":"EUVD-2026-37512","description":"Pydantic AI is a Python agent framework for building applications and workflows with Generative AI. In versions 1.56.0 through 1.101.0, 2.0.0b1, and 2.0.0b2, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix, CVE-2026-46678, did not decode, exposing cloud IAM short-term credentials. The previous remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix, so the metadata guarantee did not hold for the remaining transition forms: IPv4-compatible IPv6 (::a.b.c.d), the NAT64 RFC 8215 local-use prefix (64:ff9b:1::/48), operator-chosen NAT64 prefixes, and ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint. This occurs when an application using Pydantic AI opts a URL into force_download='allow-local' (which disables the default block on private/internal IPs) and runs on a network that actually routes the affected IPv6 transition forms: NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route these forms and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth. This is an incomplete fix of GHSA-cqp8-fcvh-x7r3 / CVE-2026-46678 (itself a follow-up to CVE-2026-25580). This issue has been fixed in version 2.0.0b3.","status":"published","published":"2026-06-16T22:49:26Z","modified":"2026-06-17T14:22:48Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T18:20:38.239877Z"}],"ghsa":[{"id":"GHSA-cg7w-rg45-pc59","title":"pydantic-ai: SSRF blocklist bypass via IPv4-compatible, SIIT/IVI, and local NAT64 IPv6 addresses (incomplete fix of CVE-2026-46678)","description":"## Summary\n\nWhen an application using Pydantic AI opts a URL into `force_download='allow-local'` (which disables the default block on private/internal IPs) **and runs on a network that routes the affected IPv6 transition forms (NAT64- or ISATAP-configured networks)**, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix did not decode — IPv4-compatible IPv6 (`::a.b.c.d`), the NAT64 RFC 8215 local-use prefix (`64:ff9b:1::/48`), operator-chosen NAT64 prefixes, or ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint, exposing cloud IAM short-term credentials.\n\n**The bypass is exploitable only in environments whose network actually routes these forms** — NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route them and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth.\n\nThis is an incomplete fix of [GHSA-cqp8-fcvh-x7r3](https://github.com/pydantic/pydantic-ai/security/advisories/GHSA-cqp8-fcvh-x7r3) / [CVE-2026-46678](https://nvd.nist.gov/vuln/detail/CVE-2026-46678) (itself a follow-up to [CVE-2026-25580](https://nvd.nist.gov/vuln/detail/CVE-2026-25580)). The prior remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix; the metadata guarantee did not hold for the remaining transition forms.\n\n## Severity\n\n**MEDIUM** — `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N` = **6.8**\n\nSame impact metrics and narrow attack surface as the parent advisory (AC:H): exploitation requires the application to have opted into `allow-local` on a URL influenced by untrusted input, and the NAT64/ISATAP variants additionally require the deployment network to route those forms.\n\n**CWE-918**: Server-Side Request Forgery (SSRF)\n\n## Affected Versions\n\n| Package | Vulnerable | Patched |\n|---|---|---|\n| `pydantic-ai` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n| `pydantic-ai-slim` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n\nThese transition forms have not been decoded since SSRF protection was introduced in `1.56.0`.\n\n## Who Is Affected\n\nUsers are affected **only if** their application explicitly opts a `FileUrl` (`ImageUrl`, `AudioUrl`, `VideoUrl`, `DocumentUrl`) into `force_download='allow-local'` on a URL that is, or could be, influenced by untrusted input.\n\nBeyond that precondition, the affected encodings only reach a metadata endpoint in environments whose network actually routes them. The broadly-routable IPv4-mapped form was addressed in `1.99.0` (CVE-2026-46678); the additional forms addressed here require a **NAT64-configured network** (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or an **ISATAP tunnel** for the ISATAP variant. The IPv4-compatible and Teredo forms are deprecated and not routed by modern stacks; they are addressed as defense-in-depth. Most deployments on a standard dual-stack cloud VM or container are therefore not exploitable in practice, but the fix restores the \"always blocked\" guarantee for the environments that are.\n\nUsers are **not** affected if they use any of the bundled integrations to ingest user input, because they do not propagate `force_download` from external data:\n\n- `Agent.to_web` / `clai web`\n- `VercelAIAdapter`\n- `AGUIAdapter` / `Agent.to_ag_ui`\n\nApplications that only download from developer-controlled URLs are not affected.\n\n## Remediation\n\nUpgrade to `1.102.0` or later (or `2.0.0b3` or later on the 2.0 pre-release line). The cloud-metadata and private-IP blocklists now decode the embedded IPv4 of every standardized IPv6 transition form before evaluating it — IPv4-mapped, IPv4-compatible, 6to4, NAT64 across all prefix lengths (including the RFC 8215 local-use prefix and operator-chosen prefixes), ISATAP, and Teredo. The set of always-blocked cloud metadata/credential endpoints has also been expanded across providers.\n\n## Workaround for Unpatched Versions\n\nAvoid passing `force_download='allow-local'` on any URL that could be influenced by untrusted input. If developers must, resolve the hostname themselves and validate the result against their own metadata blocklist — including IPv6 transition forms — before constructing the `FileUrl`.\n\n## Credits\n\nReported by [@SnailSploit](https://snailsploit.com).","status":"published","published":"2026-06-26T19:17:56Z","modified":"2026-06-26T19:17:57Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:40:33.778544Z"}],"nvd":[{"id":"CVE-2026-48782","description":"Pydantic AI is a Python agent framework for building applications and workflows with Generative AI. In versions 1.56.0 through 1.101.0, 2.0.0b1, and 2.0.0b2, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix, CVE-2026-46678, did not decode, exposing cloud IAM short-term credentials. The previous remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix, so the metadata guarantee did not hold for the remaining transition forms: IPv4-compatible IPv6 (::a.b.c.d), the NAT64 RFC 8215 local-use prefix (64:ff9b:1::/48), operator-chosen NAT64 prefixes, and ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint. This occurs when an application using Pydantic AI opts a URL into force_download='allow-local' (which disables the default block on private/internal IPs) and runs on a network that actually routes the affected IPv6 transition forms: NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route these forms and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth. This is an incomplete fix of GHSA-cqp8-fcvh-x7r3 / CVE-2026-46678 (itself a follow-up to CVE-2026-25580). This issue has been fixed in version 2.0.0b3.","status":"published","published":"2026-06-17T13:20:43.21Z","modified":"2026-08-06T18:30:13.047Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:12:24.544761Z"}],"osv":[{"id":"CVE-2026-48782","title":"pydantic-ai: SSRF blocklist bypass via IPv4-compatible, SIIT/IVI, and local NAT64 IPv6 addresses (incomplete fix of CVE-2026-46678)","description":"Pydantic AI is a Python agent framework for building applications and workflows with Generative AI. In versions 1.56.0 through 1.101.0, 2.0.0b1, and 2.0.0b2, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix, CVE-2026-46678, did not decode, exposing cloud IAM short-term credentials. The previous remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix, so the metadata guarantee did not hold for the remaining transition forms: IPv4-compatible IPv6 (::a.b.c.d), the NAT64 RFC 8215 local-use prefix (64:ff9b:1::/48), operator-chosen NAT64 prefixes, and ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint. This occurs when an application using Pydantic AI opts a URL into force_download='allow-local' (which disables the default block on private/internal IPs) and runs on a network that actually routes the affected IPv6 transition forms: NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route these forms and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth. This is an incomplete fix of GHSA-cqp8-fcvh-x7r3 / CVE-2026-46678 (itself a follow-up to CVE-2026-25580). This issue has been fixed in version 2.0.0b3.","status":"published","published":"2026-06-16T22:49:26.75Z","modified":"2026-10-28T02:30:57.167270143Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:45:06.701612Z"},{"id":"GHSA-cg7w-rg45-pc59","title":"pydantic-ai: SSRF blocklist bypass via IPv4-compatible, SIIT/IVI, and local NAT64 IPv6 addresses (incomplete fix of CVE-2026-46678)","description":"## Summary\n\nWhen an application using Pydantic AI opts a URL into `force_download='allow-local'` (which disables the default block on private/internal IPs) **and runs on a network that routes the affected IPv6 transition forms (NAT64- or ISATAP-configured networks)**, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix did not decode — IPv4-compatible IPv6 (`::a.b.c.d`), the NAT64 RFC 8215 local-use prefix (`64:ff9b:1::/48`), operator-chosen NAT64 prefixes, or ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint, exposing cloud IAM short-term credentials.\n\n**The bypass is exploitable only in environments whose network actually routes these forms** — NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route them and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth.\n\nThis is an incomplete fix of [GHSA-cqp8-fcvh-x7r3](https://github.com/pydantic/pydantic-ai/security/advisories/GHSA-cqp8-fcvh-x7r3) / [CVE-2026-46678](https://nvd.nist.gov/vuln/detail/CVE-2026-46678) (itself a follow-up to [CVE-2026-25580](https://nvd.nist.gov/vuln/detail/CVE-2026-25580)). The prior remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix; the metadata guarantee did not hold for the remaining transition forms.\n\n## Severity\n\n**MEDIUM** — `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N` = **6.8**\n\nSame impact metrics and narrow attack surface as the parent advisory (AC:H): exploitation requires the application to have opted into `allow-local` on a URL influenced by untrusted input, and the NAT64/ISATAP variants additionally require the deployment network to route those forms.\n\n**CWE-918**: Server-Side Request Forgery (SSRF)\n\n## Affected Versions\n\n| Package | Vulnerable | Patched |\n|---|---|---|\n| `pydantic-ai` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n| `pydantic-ai-slim` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n\nThese transition forms have not been decoded since SSRF protection was introduced in `1.56.0`.\n\n## Who Is Affected\n\nUsers are affected **only if** their application explicitly opts a `FileUrl` (`ImageUrl`, `AudioUrl`, `VideoUrl`, `DocumentUrl`) into `force_download='allow-local'` on a URL that is, or could be, influenced by untrusted input.\n\nBeyond that precondition, the affected encodings only reach a metadata endpoint in environments whose network actually routes them. The broadly-routable IPv4-mapped form was addressed in `1.99.0` (CVE-2026-46678); the additional forms addressed here require a **NAT64-configured network** (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or an **ISATAP tunnel** for the ISATAP variant. The IPv4-compatible and Teredo forms are deprecated and not routed by modern stacks; they are addressed as defense-in-depth. Most deployments on a standard dual-stack cloud VM or container are therefore not exploitable in practice, but the fix restores the \"always blocked\" guarantee for the environments that are.\n\nUsers are **not** affected if they use any of the bundled integrations to ingest user input, because they do not propagate `force_download` from external data:\n\n- `Agent.to_web` / `clai web`\n- `VercelAIAdapter`\n- `AGUIAdapter` / `Agent.to_ag_ui`\n\nApplications that only download from developer-controlled URLs are not affected.\n\n## Remediation\n\nUpgrade to `1.102.0` or later (or `2.0.0b3` or later on the 2.0 pre-release line). The cloud-metadata and private-IP blocklists now decode the embedded IPv4 of every standardized IPv6 transition form before evaluating it — IPv4-mapped, IPv4-compatible, 6to4, NAT64 across all prefix lengths (including the RFC 8215 local-use prefix and operator-chosen prefixes), ISATAP, and Teredo. The set of always-blocked cloud metadata/credential endpoints has also been expanded across providers.\n\n## Workaround for Unpatched Versions\n\nAvoid passing `force_download='allow-local'` on any URL that could be influenced by untrusted input. If developers must, resolve the hostname themselves and validate the result against their own metadata blocklist — including IPv6 transition forms — before constructing the `FileUrl`.\n\n## Credits\n\nReported by [@SnailSploit](https://snailsploit.com).","status":"published","published":"2026-06-26T19:17:56Z","modified":"2026-07-13T16:43:36.056155706Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:46:44.927642Z"},{"id":"PYSEC-2026-2977","title":"pydantic-ai: SSRF blocklist bypass via IPv4-compatible, SIIT/IVI, and local NAT64 IPv6 addresses (incomplete fix of CVE-2026-46678)","description":"## Summary\n\nWhen an application using Pydantic AI opts a URL into `force_download='allow-local'` (which disables the default block on private/internal IPs) **and runs on a network that routes the affected IPv6 transition forms (NAT64- or ISATAP-configured networks)**, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix did not decode — IPv4-compatible IPv6 (`::a.b.c.d`), the NAT64 RFC 8215 local-use prefix (`64:ff9b:1::/48`), operator-chosen NAT64 prefixes, or ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint, exposing cloud IAM short-term credentials.\n\n**The bypass is exploitable only in environments whose network actually routes these forms** — NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route them and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth.\n\nThis is an incomplete fix of [GHSA-cqp8-fcvh-x7r3](https://github.com/pydantic/pydantic-ai/security/advisories/GHSA-cqp8-fcvh-x7r3) / [CVE-2026-46678](https://nvd.nist.gov/vuln/detail/CVE-2026-46678) (itself a follow-up to [CVE-2026-25580](https://nvd.nist.gov/vuln/detail/CVE-2026-25580)). The prior remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix; the metadata guarantee did not hold for the remaining transition forms.\n\n## Severity\n\n**MEDIUM** — `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N` = **6.8**\n\nSame impact metrics and narrow attack surface as the parent advisory (AC:H): exploitation requires the application to have opted into `allow-local` on a URL influenced by untrusted input, and the NAT64/ISATAP variants additionally require the deployment network to route those forms.\n\n**CWE-918**: Server-Side Request Forgery (SSRF)\n\n## Affected Versions\n\n| Package | Vulnerable | Patched |\n|---|---|---|\n| `pydantic-ai` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n| `pydantic-ai-slim` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n\nThese transition forms have not been decoded since SSRF protection was introduced in `1.56.0`.\n\n## Who Is Affected\n\nUsers are affected **only if** their application explicitly opts a `FileUrl` (`ImageUrl`, `AudioUrl`, `VideoUrl`, `DocumentUrl`) into `force_download='allow-local'` on a URL that is, or could be, influenced by untrusted input.\n\nBeyond that precondition, the affected encodings only reach a metadata endpoint in environments whose network actually routes them. The broadly-routable IPv4-mapped form was addressed in `1.99.0` (CVE-2026-46678); the additional forms addressed here require a **NAT64-configured network** (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or an **ISATAP tunnel** for the ISATAP variant. The IPv4-compatible and Teredo forms are deprecated and not routed by modern stacks; they are addressed as defense-in-depth. Most deployments on a standard dual-stack cloud VM or container are therefore not exploitable in practice, but the fix restores the \"always blocked\" guarantee for the environments that are.\n\nUsers are **not** affected if they use any of the bundled integrations to ingest user input, because they do not propagate `force_download` from external data:\n\n- `Agent.to_web` / `clai web`\n- `VercelAIAdapter`\n- `AGUIAdapter` / `Agent.to_ag_ui`\n\nApplications that only download from developer-controlled URLs are not affected.\n\n## Remediation\n\nUpgrade to `1.102.0` or later (or `2.0.0b3` or later on the 2.0 pre-release line). The cloud-metadata and private-IP blocklists now decode the embedded IPv4 of every standardized IPv6 transition form before evaluating it — IPv4-mapped, IPv4-compatible, 6to4, NAT64 across all prefix lengths (including the RFC 8215 local-use prefix and operator-chosen prefixes), ISATAP, and Teredo. The set of always-blocked cloud metadata/credential endpoints has also been expanded across providers.\n\n## Workaround for Unpatched Versions\n\nAvoid passing `force_download='allow-local'` on any URL that could be influenced by untrusted input. If developers must, resolve the hostname themselves and validate the result against their own metadata blocklist — including IPv6 transition forms — before constructing the `FileUrl`.\n\n## Credits\n\nReported by [@SnailSploit](https://snailsploit.com).","status":"published","published":"2026-07-13T15:46:24.590052Z","modified":"2026-07-13T16:43:36.056155706Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:56.429374Z"},{"id":"PYSEC-2026-2981","title":"pydantic-ai: SSRF blocklist bypass via IPv4-compatible, SIIT/IVI, and local NAT64 IPv6 addresses (incomplete fix of CVE-2026-46678)","description":"## Summary\n\nWhen an application using Pydantic AI opts a URL into `force_download='allow-local'` (which disables the default block on private/internal IPs) **and runs on a network that routes the affected IPv6 transition forms (NAT64- or ISATAP-configured networks)**, the cloud-metadata blocklist could be bypassed by encoding the metadata IP in an IPv6 transition form that the previous fix did not decode — IPv4-compatible IPv6 (`::a.b.c.d`), the NAT64 RFC 8215 local-use prefix (`64:ff9b:1::/48`), operator-chosen NAT64 prefixes, or ISATAP. The IPv6 wrapper is then delivered to the underlying IPv4 metadata endpoint, exposing cloud IAM short-term credentials.\n\n**The bypass is exploitable only in environments whose network actually routes these forms** — NAT64-configured networks (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or networks with an ISATAP tunnel for ISATAP. A standard dual-stack cloud VM or container does not route them and is not affected in practice. The IPv4-compatible and Teredo variants are deprecated and addressed as defense-in-depth.\n\nThis is an incomplete fix of [GHSA-cqp8-fcvh-x7r3](https://github.com/pydantic/pydantic-ai/security/advisories/GHSA-cqp8-fcvh-x7r3) / [CVE-2026-46678](https://nvd.nist.gov/vuln/detail/CVE-2026-46678) (itself a follow-up to [CVE-2026-25580](https://nvd.nist.gov/vuln/detail/CVE-2026-25580)). The prior remediation decoded only IPv4-mapped IPv6, 6to4, and the NAT64 well-known prefix; the metadata guarantee did not hold for the remaining transition forms.\n\n## Severity\n\n**MEDIUM** — `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N` = **6.8**\n\nSame impact metrics and narrow attack surface as the parent advisory (AC:H): exploitation requires the application to have opted into `allow-local` on a URL influenced by untrusted input, and the NAT64/ISATAP variants additionally require the deployment network to route those forms.\n\n**CWE-918**: Server-Side Request Forgery (SSRF)\n\n## Affected Versions\n\n| Package | Vulnerable | Patched |\n|---|---|---|\n| `pydantic-ai` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n| `pydantic-ai-slim` | `\u003e= 1.56.0, \u003c 1.102.0`; `\u003e= 2.0.0b1, \u003c 2.0.0b3` | `1.102.0`; `2.0.0b3` |\n\nThese transition forms have not been decoded since SSRF protection was introduced in `1.56.0`.\n\n## Who Is Affected\n\nUsers are affected **only if** their application explicitly opts a `FileUrl` (`ImageUrl`, `AudioUrl`, `VideoUrl`, `DocumentUrl`) into `force_download='allow-local'` on a URL that is, or could be, influenced by untrusted input.\n\nBeyond that precondition, the affected encodings only reach a metadata endpoint in environments whose network actually routes them. The broadly-routable IPv4-mapped form was addressed in `1.99.0` (CVE-2026-46678); the additional forms addressed here require a **NAT64-configured network** (IPv6-only or dual-stack-with-NAT64 deployments, including some Kubernetes setups) for the NAT64 variants, or an **ISATAP tunnel** for the ISATAP variant. The IPv4-compatible and Teredo forms are deprecated and not routed by modern stacks; they are addressed as defense-in-depth. Most deployments on a standard dual-stack cloud VM or container are therefore not exploitable in practice, but the fix restores the \"always blocked\" guarantee for the environments that are.\n\nUsers are **not** affected if they use any of the bundled integrations to ingest user input, because they do not propagate `force_download` from external data:\n\n- `Agent.to_web` / `clai web`\n- `VercelAIAdapter`\n- `AGUIAdapter` / `Agent.to_ag_ui`\n\nApplications that only download from developer-controlled URLs are not affected.\n\n## Remediation\n\nUpgrade to `1.102.0` or later (or `2.0.0b3` or later on the 2.0 pre-release line). The cloud-metadata and private-IP blocklists now decode the embedded IPv4 of every standardized IPv6 transition form before evaluating it — IPv4-mapped, IPv4-compatible, 6to4, NAT64 across all prefix lengths (including the RFC 8215 local-use prefix and operator-chosen prefixes), ISATAP, and Teredo. The set of always-blocked cloud metadata/credential endpoints has also been expanded across providers.\n\n## Workaround for Unpatched Versions\n\nAvoid passing `force_download='allow-local'` on any URL that could be influenced by untrusted input. If developers must, resolve the hostname themselves and validate the result against their own metadata blocklist — including IPv6 transition forms — before constructing the `FileUrl`.\n\n## Credits\n\nReported by [@SnailSploit](https://snailsploit.com).","status":"published","published":"2026-07-13T15:46:24.440536Z","modified":"2026-07-13T16:43:36.056155706Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:56.429374Z"},{"id":"ROOT-APP-PYPI-CVE-2026-48782","title":"CVE-2026-48782 in pydantic-ai-slim - Patched by Root","description":"Root has patched CVE-2026-48782 in the pydantic-ai-slim package for Root:PyPI. Multiple fixed versions available.","status":"published","published":"2026-08-03T06:38:38Z","modified":"2026-08-03T13:45:07.380306806Z","updated_at":"2026-11-02T15:53:28.259095Z"}]}}
