Secure Autonomous
FeedbackGet alertsCheck a deployment
Cases / REG-0027

Pydantic AI: a web page can make a developer's local agent run and execute tools, including tools marked as requiring approval, fixed August 2026

Caught first by researchersSoftware agents · Enterprise work agentsMachine acts aloneDemonstration
REG-0027Updated 2026-10-157 sources, 7 linkedDisclosure corroborated

What happened

A developer running a Pydantic AI agent locally through Agent.to_web() or the clai web development chat. The agent served by the local chat endpoint, holding the privileges and credentials of the local process. A request submitted by a website the developer visits, to the loopback-hosted chat server; the endpoint did not validate the request content type. not evidenced in source. The agent's tools ran with the privileges and credentials of the local process; binding to localhost did not prevent a browser page from reaching it. The served agent runs and executes tools on the attacker's request. Outcome: averted by disclosure; none reported; the maintainer's advisory rates the flaw High, 7.6 on version 3.1 of the Common Vulnerability Scoring System (CVSS, a severity score); the National Vulnerability Database (NVD) carries this score from GitHub, the CVE Numbering Authority, and added none of its own; as of Oct 2026. Coordinated disclosure through the maintainer's security advisory, which credits Thai Son Dinh of VinSOC Labs (research and development) as the reporter.

Verification: 6 of 6 checks complete
✓ Structured and checkedevery claim typed and sourced, then checked by the Register's automated checker for missing sources and mistyped claims
✓ Sources linked7 of 7 sources link to the record (7 to a primary record)
✓ Sources checked claim by claimevery claim checked against its source on 2026-10-22
✓ Interpretation checked statement by statementeach statement of the Register's interpretation checked against a source on 2026-10-21
✓ Reviewed by the editorreviewed 2026-10-15
✓ Reply offeredPydantic: offered
Corrections · 13, latest 2026-10-22

Changes to what this case says, with the reason. Every earlier version is kept.

  • 2026-10-22: Outcome: regime consequence. Rule 13 (new cases): the consequence line records only actions by a regulator, court, legislature or other government body; a cve, an advisory, a score or a fix is not one. the cve and fix details are already in the evidence and recovery fields, so nothing is lost. found while drafting this case's letters, 22 october 2026.
    Show the change
    Before: CVE-2026-107295 (Common Vulnerabilities and Exposures identifier), published 8 October 2026; fixed in 1.107.4 and 2.28.0, released 12 August 2026
    After: none
  • 2026-10-21: Inference: value. Found in the editor's second, independent check of the interpretations, 21 october 2026: the second fix also accepts any ip address, which is not a host name: the maintainer's documentation at commit 871c7aee says the server answers only requests whose host header is an ip address or localhost, unless a host is explicitly allowed (ghsa-q2xc-rrxj-58x9).
    Show the change
    Before: The maintainer's own documentation says the chat server trusts whatever approval decision the client sends, so any client that can reach the endpoint can approve a pending tool call, and calls approval prompts a convenience for the developer rather than an authorization control. The August 2026 fixes kept that design and instead stopped web pages from reaching the endpoint: it now accepts only requests sent as JavaScript Object Notation (JSON), which a browser will not send to another site without a permission check the server refuses, and, after a second fix two days later, only requests addressed to a local or explicitly allowed host name. The record does not show exploitation, a public proof of concept, or harm to any developer
    After: The maintainer's own documentation says the chat server trusts whatever approval decision the client sends, so any client that can reach the endpoint can approve a pending tool call, and calls approval prompts a convenience for the developer rather than an authorization control. The August 2026 fixes kept that design and instead stopped web pages from reaching the endpoint: it now accepts only requests sent as JavaScript Object Notation (JSON), which a browser will not send to another site without a permission check the server refuses, and, after a second fix two days later, only requests addressed to localhost, an Internet Protocol (IP) address, or an explicitly allowed host name. The record does not show exploitation, a public proof of concept, or harm to any developer
  • 2026-10-21: Sources: ghsa: date. Found in the editor's source check of 21 october 2026: the repository advisory page reads 'dsfaccini published ghsa-h4xc-3qfq-jf93 aug 12, 2026'; 2026-10-08 is the date of the github advisory database entry and the nvd record, not of this page.
    Show the change
    Before: 2026-10-08
    After: 2026-08-12
  • 2026-10-21: Sources: ghsa: title. Found in the editor's source check of 21 october 2026: the title was not the advisory's headline and named pull requests and releases that the advisory page, as read, does not list; the exact headline is used.
    Show the change
    Before: Pydantic AI security advisory GHSA-h4xc-3qfq-jf93, with fix pull requests 7382 and 7383 and releases v1.107.4 and v2.28.0
    After: Web chat UI (`Agent.to_web()`, `clai web`): a website visited by the developer can trigger agent runs and server-side tool execution on the local chat endpoint (Pydantic AI security advisory GHSA-h4xc-3qfq-jf93)
  • 2026-10-21: Inference: source ids. Found in the editor's source check of 21 october 2026: the interpretation now rests on the maintainer's fix commit d2690201 and companion advisory ghsa-q2xc-rrxj-58x9 as well as ghsa-h4xc-3qfq-jf93.
    Show the change
    Before: ["GHSA"]
    After: ["GHSA", "FIX-7382", "GHSA-Q2XC"]
  • 2026-10-21: Inference: value. Found in the editor's source check of 21 october 2026: the sentence 'the approval decision has to be checked where the tool runs' is a prescription no source makes, and the interpretation did not say what the record does not show. the maintainer's documentation in fix commit d2690201 says 'any client that can reach the endpoint can approve any pending call' and to 'treat approval prompts as a convenience ... rather than an authorization control'; the fix requires 'content-type: application/json', which a browser 'cannot send cross-origin without a preflight that the server refuses'; advisory ghsa-q2xc-rrxj-58x9 adds the host header check. no source reports exploitation (nvd record: the cybersecurity and infrastructure security agency's stakeholder-specific vulnerability categorization gives exploitation 'none'). the interpretation was not signed (signed_by null).
    Show the change
    Before: An approval gate enforced by the client is an instruction to the client, not a mechanism: any caller that can reach the server can skip it. The approval decision has to be checked where the tool runs
    After: The maintainer's own documentation says the chat server trusts whatever approval decision the client sends, so any client that can reach the endpoint can approve a pending tool call, and calls approval prompts a convenience for the developer rather than an authorization control. The August 2026 fixes kept that design and instead stopped web pages from reaching the endpoint: it now accepts only requests sent as JavaScript Object Notation (JSON), which a browser will not send to another site without a permission check the server refuses, and, after a second fix two days later, only requests addressed to a local or explicitly allowed host name. The record does not show exploitation, a public proof of concept, or harm to any developer
  • 2026-10-21: Fields: recovery accountability. Found in the editor's source check of 21 october 2026: the reporter was not named. the advisory ghsa-h4xc-3qfq-jf93 credits 'thai son dinh from vinsoc labs (r&d)' and lists the reporter account sondt99.
    Show the change
    Before: Coordinated disclosure through the maintainer's security advisory
    After: Coordinated disclosure through the maintainer's security advisory, which credits Thai Son Dinh of VinSOC Labs (research and development) as the reporter
  • 2026-10-21: Fields: recovery technical: source ids. Found in the editor's source check of 21 october 2026: the pull requests and release dates come from the nvd record, the maintainer's release pages and fix commit d2690201, and the dns rebinding fix from the maintainer's advisory ghsa-q2xc-rrxj-58x9; those sources are added.
    Show the change
    Before: ["GHSA"]
    After: ["GHSA", "NVD-107295", "FIX-7382", "REL-2-28-0", "REL-1-107-4", "GHSA-Q2XC"]
  • 2026-10-21: Fields: recovery technical. Found in the editor's source check of 21 october 2026: the release date was missing and the pull requests are not on the advisory page as read. the release pages show v2.28.0 and v1.107.4 released on 12 august 2026, listing #7382 and the v1 backport #7383; fix commit d2690201 is dated 11 august 2026. the maintainer's companion advisory ghsa-q2xc-rrxj-58x9 ('the local chat endpoint does not validate the host header', published 14 august 2026) lists versions below 1.107.5 and 2.30.0 as affected, so 1.107.4 and 2.28.0 remained reachable by dns rebinding; 1.107.5 and 2.30.0 were uploaded to the python package index (pypi) on 14 august 2026.
    Show the change
    Before: Fixed in versions 1.107.4 and 2.28.0 via pull requests 7382 and 7383
    After: Fixed in versions 1.107.4 and 2.28.0, released on 12 August 2026, via pull requests 7382 and 7383 (merged 11 August 2026), which make the chat endpoint refuse requests not sent as JavaScript Object Notation (JSON). A companion advisory on the same chat endpoint, GHSA-q2xc-rrxj-58x9, found that versions with this fix could still be reached from a web page by Domain Name System (DNS) rebinding because the server did not check the Host header; that was fixed in 1.107.5 and 2.30.0, released on 14 August 2026
  • 2026-10-21: Fields: evidence event. Found in the editor's source check of 21 october 2026: the maintainer's advisory ghsa-h4xc-3qfq-jf93 lists two weaknesses, cwe-346 origin validation error and cwe-352 cross-site request forgery, and shows 'published ... aug 12, 2026'; the github advisory database entry is dated 2026-10-08 and the nvd record (published 2026-10-08) lists only cwe-352.
    Show the change
    Before: Maintainer advisory GHSA-h4xc-3qfq-jf93; NVD record published 8 October 2026; weakness classified as cross-site request forgery (CWE-352)
    After: Maintainer advisory GHSA-h4xc-3qfq-jf93, published on the project's repository on 12 August 2026 and in the GitHub Advisory Database on 8 October 2026; NVD record CVE-2026-107295 published 8 October 2026. The advisory classifies the weakness as origin validation error (Common Weakness Enumeration CWE-346) and cross-site request forgery (CWE-352); the NVD record lists only CWE-352
  • 2026-10-21: Outcome: regime consequence. Found in the editor's source check of 21 october 2026: the dates that separate the fix from the cve were missing. the nvd record was published 2026-10-08; the maintainer's release pages for v1.107.4 and v2.28.0 show them released on 12 august 2026 (python package index uploads 2026-08-12).
    Show the change
    Before: CVE-2026-107295; fixed in 1.107.4 and 2.28.0
    After: CVE-2026-107295 (Common Vulnerabilities and Exposures identifier), published 8 October 2026; fixed in 1.107.4 and 2.28.0, released 12 August 2026
  • 2026-10-21: Outcome: severity. Found in the editor's source check of 21 october 2026: the case did not say who assigned the score. the nvd record for cve-2026-107295 lists the 7.6 score (vector cvss:3.1/av:n/ac:l/pr:n/ui:r/s:u/c:l/i:h/a:l) with source security-advisories@github.com as a 'secondary' score and no nvd score; the maintainer's advisory ghsa-h4xc-3qfq-jf93 gives severity high, 7.6.
    Show the change
    Before: none reported (CVSS 3.1 base 7.6)
    After: none reported; the maintainer's advisory rates the flaw High, 7.6 on version 3.1 of the Common Vulnerability Scoring System (CVSS, a severity score); the National Vulnerability Database (NVD) carries this score from GitHub, the CVE Numbering Authority, and added none of its own
  • 2026-10-21: Title. Found in the editor's source check of 21 october 2026: the fix shipped in august, not october. the maintainer's release pages show v2.28.0 'released this 12 aug' and v1.107.4 'released this 12 aug' (both headed 2026-08-11), and the repository advisory ghsa-h4xc-3qfq-jf93 was published on 12 august 2026; october 2026 is when the cve (common vulnerabilities and exposures) record and the github advisory database entry were published (8 october).
    Show the change
    Before: Pydantic AI: a web page can make a developer's local agent run and execute tools, including tools marked as requiring approval, fixed October 2026
    After: Pydantic AI: a web page can make a developer's local agent run and execute tools, including tools marked as requiring approval, fixed August 2026
Record history · 8 entries
  • 2026-10-21: Source added: Add `allowed_hosts` to `Agent.to_web()` and `clai web` (#7437) (Pydantic AI commit 871c7aee).
  • 2026-10-21: Source added: Web chat UI (`Agent.to_web()`, `clai web`): the local chat endpoint does not validate the `Host` header (Pydantic AI security advisory GHSA-q2xc-rrxj-58x9).
  • 2026-10-21: Source added: v1.107.4 (2026-08-11) (Pydantic AI release).
  • 2026-10-21: Source added: v2.28.0 (2026-08-11) (Pydantic AI release).
  • 2026-10-21: Source added: Only accept JSON request bodies on the web UI chat endpoint (#7382) (Pydantic AI commit d2690201).
  • 2026-10-15: Pydantic acknowledged receipt.
  • 2026-10-14: Right of reply offered to Pydantic.
  • 2026-10-14: Checked by the editor against the linked records.

Controls that address what went wrong

3 controls missing or failed; 1 in place and worked. The line under each is the concrete form it would have taken in this case.

Actor identity verification
Request origin not verified (no content-type validation)
Failed · Actor layer
Destructive-action gate
Client-relayed approval left requires_approval tools exposed
Failed · Envelope layer
Least-privilege credential scoped to task
Tools ran with the full privileges and credentials of the local process
Absent · Envelope layer
Coordinated disclosure program
Coordinated disclosure and fix
Worked · External layer

New cases like this, once a week. A short email when a case, signal or rule touches software agents. Free; unsubscribe in one click.

Get the weekly email

How it unfolded, layer by layer

MandateWhat it was told to do
Who deployed it: A developer running a Pydantic AI agent locally through Agent.to_web() or the clai web development chat. The task: Serve a local chat interface for developing and testing an agent.
ActorWhat acted
The agent served by the local chat endpoint, holding the privileges and credentials of the local process
InputsWhat it could see
A request submitted by a website the developer visits, to the loopback-hosted chat server; the endpoint did not validate the request content type
DecisionHow it chose
not evidenced in source
EnvelopeWhat it was allowed to do
Authority it held: The agent's tools ran with the privileges and credentials of the local process; binding to localhost did not prevent a browser page from reaching it. Limits in place: Tools marked requires_approval remained exposed because approval decisions were relayed by the client.
ActionWhat it did
The served agent runs and executes tools on the attacker's request
OutcomeWhat happened
Caught first by researchers. Severity: none reported; the maintainer's advisory rates the flaw High, 7.6 on version 3.1 of the Common Vulnerability Scoring System (CVSS, a severity score); the National Vulnerability Database (NVD) carries this score from GitHub, the CVE Numbering Authority, and added none of its own.
EvidenceWhat can be proven
Record of the event: Maintainer advisory GHSA-h4xc-3qfq-jf93, published on the project's repository on 12 August 2026 and in the GitHub Advisory Database on 8 October 2026; NVD record CVE-2026-107295 published 8 October 2026. The advisory classifies the weakness as origin validation error (Common Weakness Enumeration CWE-346) and cross-site request forgery (CWE-352); the NVD record lists only CWE-352.
RecoveryWhat could be stopped, undone, answered for
Technical recovery: Fixed in versions 1.107.4 and 2.28.0, released on 12 August 2026, via pull requests 7382 and 7383 (merged 11 August 2026), which make the chat endpoint refuse requests not sent as JavaScript Object Notation (JSON). A companion advisory on the same chat endpoint, GHSA-q2xc-rrxj-58x9, found that versions with this fix could still be reached from a web page by Domain Name System (DNS) rebinding because the server did not check the Host header; that was fixed in 1.107.5 and 2.30.0, released on 14 August 2026. Accountability: Coordinated disclosure through the maintainer's security advisory, which credits Thai Son Dinh of VinSOC Labs (research and development) as the reporter.

The same gap in other cases

Cases where the same control was missing or failed. Those in another world are the cross-domain comparisons the Register exists to make.

ControlSame worldOther worlds
Actor identity verificationAgent-run intrusion campaign 2025, Claude Code [bot] trust 2026Kia dealer portal 2024 (machines)
Destructive-action gatePocketOS 2026, Replit and SaaStr 2025Triton 2017 (machines), Gemini calendar invite 2025 (software acting on machines)
Least-privilege credential scoped to taskGitHub MCP leak 2025, PocketOS 2026, Claude Code [bot] trust 2026, Perplexity Comet 2025·

Cost and accountability

Severitynone reported; the maintainer's advisory rates the flaw High, 7.6 on version 3.1 of the Common Vulnerability Scoring System (CVSS, a severity score); the National Vulnerability Database (NVD) carries this score from GitHub, the CVE Numbering Authority, and added none of its own
AffectedNot recorded
Costnone reported
Regulatory or legal consequencenone
Technical recoveryTechnical recovery: Fixed in versions 1.107.4 and 2.28.0, released on 12 August 2026, via pull requests 7382 and 7383 (merged 11 August 2026), which make the chat endpoint refuse requests not sent as JavaScript Object Notation (JSON). A companion advisory on the same chat endpoint, GHSA-q2xc-rrxj-58x9, found that versions with this fix could still be reached from a web page by Domain Name System (DNS) rebinding because the server did not check the Host header; that was fixed in 1.107.5 and 2.30.0, released on 14 August 2026.
AccountabilityCoordinated disclosure through the maintainer's security advisory, which credits Thai Son Dinh of VinSOC Labs (research and development) as the reporter
InterpretationWhy it matters beyond its domain. The maintainer's own documentation says the chat server trusts whatever approval decision the client sends, so any client that can reach the endpoint can approve a pending tool call, and calls approval prompts a convenience for the developer rather than an authorization control. The August 2026 fixes kept that design and instead stopped web pages from reaching the endpoint: it now accepts only requests sent as JavaScript Object Notation (JSON), which a browser will not send to another site without a permission check the server refuses, and, after a second fix two days later, only requests addressed to localhost, an Internet Protocol (IP) address, or an explicitly allowed host name. The record does not show exploitation, a public proof of concept, or harm to any developer. Signed by Saurabh Bhatnagar on 2026-10-21.

Right of reply

Named partyStatus
PydanticOffered 2026-10-14; receipt acknowledged 2026-10-15; awaiting responseRespond for Pydantic

Help shape the Register

A person reads every answer; changes it leads to are logged in the methodology. To dispute a claim or reply for a named company, use Respond, dispute, or submit.

Did this page help with what you came to do?