Secure Autonomous
FeedbackGet alertsCheck a deployment
Cases / REG-0005

GitHub MCP server: a public issue hijacks a user's agent into leaking private-repository data, disclosed 26 May 2025

Caught first by researchersSoftware agents · Enterprise work agentsHuman supervisesDemonstration
REG-0005Updated 2026-10-284 sources, 4 linkedDisclosure corroborated

Disclosure: The editor owns shares in Microsoft, which owns GitHub, a long-term holding from before the Register began. See Independence.

What happened

Researchers showed that a prompt injection in a public GitHub issue could lead a coding agent using the GitHub MCP server to read the user's private repositories and leak their data into a public pull request. On the record, the agent's token reached private repositories as well as the public one, and the agent treated issue text as instructions. A GitHub maintainer listed mitigations, including read-only modes and fine-grained tokens.

A plain summary of the typed record below; where they differ, the record governs.

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 linked4 of 4 sources link to the record (2 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-22
✓ Reviewed by the editorreviewed 2026-10-28
✓ Reply offeredGitHub: offered
Corrections · 39, latest 2026-10-22

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

  • 2026-10-22: Controls: c-e5. Found in the third independent re-read of 22 october 2026: the lead-in asserted that per-call prompts were in force and failed, but the researchers never state their run's setting (inv gives only claude desktop's default) and issue #844's text says nothing per call; the note itself goes on to say the setting is not recorded. narrowed to what the sources show (inv, gh-844).
    Show the change
    Before: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used; the author of the reproduction posted in issue #844 writes that there is human-in-the-loop verification, a 'Continue' button with a 'See More' preview of what the click will do
    After: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. No approval prompt is recorded stopping it: Claude Desktop, used in the researchers' run, confirms individual tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used; the author of the reproduction posted in issue #844 writes that there is human-in-the-loop verification, a 'Continue' button with a 'See More' preview of what the click will do
  • 2026-10-22: Inference: value. Found in the second independent re-read of 22 october 2026: the issue's readable text says there is human-in-the-loop verification, a 'continue' button and a 'see more' preview; that the prompt appears per tool call rested on the screenshots, which cannot be read by permitted means (rule 21), so the claim is narrowed to the author's words (gh-844).
    Show the change
    Before: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in the researchers' run (the posted reproduction shows a per-call 'Continue' prompt), and shows no attack outside the demonstrations
    After: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in the researchers' run (the author of the posted reproduction writes that there is human-in-the-loop verification, a 'Continue' button with a 'See More' preview of what the click will do), and shows no attack outside the demonstrations
  • 2026-10-22: Controls: c-e5. Found in the second independent re-read of 22 october 2026: the issue's readable text says there is human-in-the-loop verification, a 'continue' button and a 'see more' preview; that the prompt appears per tool call rested on the screenshots, which cannot be read by permitted means (rule 21), so the claim is narrowed to the author's words (gh-844).
    Show the change
    Before: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used; the reproduction posted in issue #844 shows a per-call 'Continue' prompt with a 'See More' preview
    After: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used; the author of the reproduction posted in issue #844 writes that there is human-in-the-loop verification, a 'Continue' button with a 'See More' preview of what the click will do
  • 2026-10-22: Context: autonomy level text. Found in the second independent re-read of 22 october 2026: the issue's readable text says there is human-in-the-loop verification, a 'continue' button and a 'see more' preview; that the prompt appears per tool call rested on the screenshots, which cannot be read by permitted means (rule 21), so the claim is narrowed to the author's words (gh-844).
    Show the change
    Before: Machine acts, human supervises (Claude Desktop asks the user to confirm each tool call by default; the researchers say many users choose Always Allow; the researchers do not say which setting their run used; the reproduction posted in issue #844 shows a per-call 'Continue' prompt)
    After: Machine acts, human supervises (Claude Desktop asks the user to confirm each tool call by default; the researchers say many users choose Always Allow; the researchers do not say which setting their run used; the author of the reproduction posted in issue #844 writes that there is human-in-the-loop verification, a 'Continue' button with a 'See More' preview of what the click will do)
  • 2026-10-22: Inference: signed by. The interpretation's wording changed after the editor signed it (re-read of 22 october 2026); the signature is cleared so the editor signs the corrected wording.
    Show the change
    Before: Saurabh Bhatnagar
    After:
  • 2026-10-22: Inference: value. Found in the independent re-read of 22 october 2026: the phrases 'in github copilot in visual studio code' and 'before the write that leaked the data' rest on screenshots in issue #844 that the earlier check read through a proxy of a site the fetch tool declines (rule 21), and the reader of 22 october could not open them by permitted means; the claim is narrowed to what the issue's text shows (gh-844).
    Show the change
    Before: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in the researchers' run (the posted reproduction shows a per-call 'Continue' prompt before the write that leaked the data), and shows no attack outside the demonstrations
    After: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in the researchers' run (the posted reproduction shows a per-call 'Continue' prompt), and shows no attack outside the demonstrations
  • 2026-10-22: Controls: c-e5. Found in the independent re-read of 22 october 2026: the phrases 'in github copilot in visual studio code' and 'before the write that leaked the data' rest on screenshots in issue #844 that the earlier check read through a proxy of a site the fetch tool declines (rule 21), and the reader of 22 october could not open them by permitted means; the claim is narrowed to what the issue's text shows (gh-844).
    Show the change
    Before: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used; the reproduction posted in issue #844, in GitHub Copilot in Visual Studio Code, shows a per-call 'Continue' prompt with a 'See More' preview before the write that leaked the data
    After: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used; the reproduction posted in issue #844 shows a per-call 'Continue' prompt with a 'See More' preview
  • 2026-10-22: Context: autonomy level text. Found in the independent re-read of 22 october 2026: the phrases 'in github copilot in visual studio code' and 'before the write that leaked the data' rest on screenshots in issue #844 that the earlier check read through a proxy of a site the fetch tool declines (rule 21), and the reader of 22 october could not open them by permitted means; the claim is narrowed to what the issue's text shows (gh-844).
    Show the change
    Before: Machine acts, human supervises (Claude Desktop asks the user to confirm each tool call by default; the researchers say many users choose Always Allow; the researchers do not say which setting their run used; the reproduction posted in issue #844, in GitHub Copilot in Visual Studio Code, shows a per-call 'Continue' prompt before the write that leaked the data)
    After: Machine acts, human supervises (Claude Desktop asks the user to confirm each tool call by default; the researchers say many users choose Always Allow; the researchers do not say which setting their run used; the reproduction posted in issue #844 shows a per-call 'Continue' prompt)
  • 2026-10-21: Controls: c-e5. Found in the editor's second, independent check of the interpretations, 21 october 2026: third check: clarity; the second verb belongs to the researchers, not the users.
    Show the change
    Before: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow and do not say which setting their run used; the reproduction posted in issue #844, in GitHub Copilot in Visual Studio Code, shows a per-call 'Continue' prompt with a 'See More' preview before the write that leaked the data
    After: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used; the reproduction posted in issue #844, in GitHub Copilot in Visual Studio Code, shows a per-call 'Continue' prompt with a 'See More' preview before the write that leaked the data
  • 2026-10-21: Inference: signed by. The interpretation's wording changed after the editor signed it (second, independent check of 21 october 2026); the signature is cleared so the editor signs the corrected wording.
    Show the change
    Before: Saurabh Bhatnagar
    After:
  • 2026-10-21: Controls: c-e5. Found in the editor's second, independent check of the interpretations, 21 october 2026: the note mixed the two runs: the posted reproduction ran in github copilot in visual studio code and shows the per-call prompt in force (gh-844); the researchers' run used claude desktop and does not record the setting (inv).
    Show the change
    Before: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts were present (Claude Desktop confirms tool calls by default; the reproduction shows a 'Continue' button with a 'See More' preview) and did not stop it; the researchers say many users choose Always Allow; neither run records which setting was in force
    After: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts did not stop it: Claude Desktop, used in the researchers' run, confirms tool calls by default, though the researchers say many users choose Always Allow and do not say which setting their run used; the reproduction posted in issue #844, in GitHub Copilot in Visual Studio Code, shows a per-call 'Continue' prompt with a 'See More' preview before the write that leaked the data
  • 2026-10-21: Context: autonomy level text. Found in the editor's second, independent check of the interpretations, 21 october 2026: the posted reproduction does show the setting in force (a per-call prompt), and it ran in github copilot in visual studio code, not claude desktop (gh-844).
    Show the change
    Before: Machine acts, human supervises (Claude Desktop asks the user to confirm each tool call by default; the researchers say many users choose Always Allow; neither run records which setting was in force)
    After: Machine acts, human supervises (Claude Desktop asks the user to confirm each tool call by default; the researchers say many users choose Always Allow; the researchers do not say which setting their run used; the reproduction posted in issue #844, in GitHub Copilot in Visual Studio Code, shows a per-call 'Continue' prompt before the write that leaked the data)
  • 2026-10-21: Inference: value. Found in the editor's second, independent check of the interpretations, 21 october 2026: the reproduction posted in issue #844, run in github copilot in visual studio code, shows a per-call 'continue' prompt on the file-write call that carried the leaked data, and its author writes 'technically, there is human-in-the-loop verification' (gh-844).
    Show the change
    Before: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in either run, and shows no attack outside the demonstrations
    After: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in the researchers' run (the posted reproduction shows a per-call 'Continue' prompt before the write that leaked the data), and shows no attack outside the demonstrations
  • 2026-10-21: Inference: value. Found in the editor's second, independent check of the interpretations, 21 october 2026: issue #844 says the public-only token could read private repositories 'but not write information from them' (gh-844).
    Show the change
    Before: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in either run, and shows no attack outside the demonstrations
    After: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in either run, and shows no attack outside the demonstrations
  • 2026-10-21: Inference: value. Found in the editor's second, independent check of the interpretations, 21 october 2026: invariant's post calls limiting access 'critical', says token-based permissions offer 'some protection', and gives the one-repository rule as an example policy for its own product (inv).
    Show the change
    Before: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers say limiting the agent to the repositories it needs offers some protection and recommend a one-repository-per-session rule, but the posted reproduction reports that a token limited to public repositories still read private repositories, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in either run, and shows no attack outside the demonstrations
    After: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in either run, and shows no attack outside the demonstrations
  • 2026-10-21: Controls: c-a1. Editor's classification call of 21 october 2026 (call 2, accepted from pull request #74): the issue author's identity was not in doubt, so actor identity verification does not fit; the gap was a filter on whose content the agent reads, which has no canonical control, so it is recorded as unmapped.
    Show the change
    Before: {"bucket": "absent", "id": "C-A1", "note": "The issue author's identity was not in doubt (any GitHub user May open an issue on a public repository); what was missing was a filter on whose content the agent reads, later shipped by GitHub as opt-in lockdown mode on 10 December 2025. Bucket left as the editor's pending call on whether this control fits", "confidence": "medium", "basis": "curated"}
    After: {"unmapped": "Content-source trust filter (not in the canonical set): The issue author's identity was not in doubt (any GitHub user May open an issue on a public repository); what was missing was a filter on whose content the agent reads, later shipped by GitHub as opt-in lockdown mode on 10 December 2025"}
  • 2026-10-21: Controls: c-e3. Editor's classification call of 21 october 2026 (call 1, accepted from pull request #74): the approval prompts existed and did not stop the public pull request; the action was not irreversible destruction but data leaving for a public place, so the missing control is a limit on where data can go (containment and egress, c-e5), recorded as absent. the prompt facts are kept in the note.
    Show the change
    Before: {"bucket": "failed", "id": "C-E3", "note": "Per-call approval prompts were present (Claude Desktop confirms tool calls by default; the reproduction shows a 'Continue' button with a 'See More' preview) and did not stop the public pull request; the researchers say many users choose Always Allow; neither run records which setting was in force", "confidence": "medium", "basis": "curated"}
    After: {"bucket": "absent", "id": "C-E5", "note": "No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. Per-call approval prompts were present (Claude Desktop confirms tool calls by default; the reproduction shows a 'Continue' button with a 'See More' preview) and did not stop it; the researchers say many users choose Always Allow; neither run records which setting was in force", "confidence": "medium", "basis": "curated"}
  • 2026-10-20: Provenance tier text. Found in the editor's source re-check of 19-20 october 2026: issue #844 is an anonymous user's report; nothing in the record establishes independence from the researchers.
    Show the change
    Before: Researcher disclosure with independent reproduction
    After: Researcher disclosure with a reproduction posted on the server's issue tracker (independence not established)
  • 2026-10-20: Inference: value. Found in the editor's source re-check of 19-20 october 2026: the counterfactual 'would have had nothing private to leak' was the register's, not a source's; invariant labs says token-based permissions 'offer some protection', and issue #844 reports a public-only token still read private repositories. the interpretation was unsigned (signed_by null), so no signature is cleared.
    Show the change
    Before: The injected text was the trigger, but the excess authority made the harm possible. With a token scoped to one repository, the same injection would have had nothing private to leak
    After: The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers say limiting the agent to the repositories it needs offers some protection and recommend a one-repository-per-session rule, but the posted reproduction reports that a token limited to public repositories still read private repositories, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in either run, and shows no attack outside the demonstrations
  • 2026-10-20: Controls: c-a1. Found in the editor's source re-check of 19-20 october 2026: invariant labs: 'by standard github rules, an attacker can now create a malicious issue on the public repository'; github changelog 10 december 2025 describes lockdown mode as surfacing only content from users with push access.
    Show the change
    Before: Trust filtering on issue authors
    After: The issue author's identity was not in doubt (any GitHub user May open an issue on a public repository); what was missing was a filter on whose content the agent reads, later shipped by GitHub as opt-in lockdown mode on 10 December 2025. Bucket left as the editor's pending call on whether this control fits
  • 2026-10-20: Controls: c-e3: confidence. Found in the editor's source re-check of 19-20 october 2026: the counterfactual (whether a prompt reviewed before clicking would have stopped the leak) is not shown in the sources.
    Show the change
    Before: high
    After: medium
  • 2026-10-20: Controls: c-e3. Found in the editor's source re-check of 19-20 october 2026: the old note asserted the prompts were 'bypassed by always-allow habits'; invariant labs says only that many users opt for always allow, and issue #844 shows a continue prompt; neither says which setting its run used. bucket left as the editor's pending call.
    Show the change
    Before: Approval prompts (bypassed by always-allow habits)
    After: Per-call approval prompts were present (Claude Desktop confirms tool calls by default; the reproduction shows a 'Continue' button with a 'See More' preview) and did not stop the public pull request; the researchers say many users choose Always Allow; neither run records which setting was in force
  • 2026-10-20: Fields: recovery accountability: source ids. Found in the editor's source re-check of 19-20 october 2026: issue #844 carries the maintainer's account.
    Show the change
    Before: ["INV"]
    After: ["INV", "GH-844"]
  • 2026-10-20: Fields: recovery accountability. Found in the editor's source re-check of 19-20 october 2026: 'no regulator involved' was written without a source saying so; reworded to what the record shows, and the maintainer's own account on issue #844 (21 april 2026) added next to it (runbook rule 16).
    Show the change
    Before: No regulator involved; the researchers published on 26 May 2025, and no record of prior disclosure to GitHub is public
    After: The researchers published on 26 May 2025; the sources record no disclosure to GitHub before publication and no regulator action. On the server's tracker a question whether a CVE (a public vulnerability identifier) was issued went unanswered, and a GitHub maintainer wrote on 21 April 2026 that the report 'was reviewed' but was 'not really a vulnerability in the conventional sense'
  • 2026-10-20: Fields: recovery technical: source ids. Found in the editor's source re-check of 19-20 october 2026: new source gh-lockdown added for the shipped mitigation.
    Show the change
    Before: ["GH-844", "DEVCLASS"]
    After: ["GH-LOCKDOWN", "GH-844", "DEVCLASS"]
  • 2026-10-20: Fields: recovery technical. Found in the editor's source re-check of 19-20 october 2026: the field omitted the fix github shipped: the github changelog of 10 december 2025 ('lockdown mode ensures that only content from trusted collaborators with push access is surfaced'; 'private repositories are unaffected'); the maintainer's comments on issue #844 are dated 20 and 21 april 2026.
    Show the change
    Before: A GitHub maintainer called it an example of the 'lethal trifecta' risk for agents rather than a vulnerability in the conventional sense, and listed mitigations including lockdown and read-only modes and fine-grained tokens; a proposal to accept issues only from users with push access was raised in the server's tracker (issue #427, per DevClass)
    After: On 10 December 2025 GitHub shipped an opt-in 'lockdown mode' for its MCP server, enabled by a request header, which surfaces only content from collaborators with push access on public repositories (private repositories are unaffected), and said content sanitization against prompt injection is on by default. On the server's issue tracker a GitHub maintainer listed mitigations on 20 April 2026 (lockdown mode, read-only mode, secret scanning on public-repository calls, OAuth 2.1, strict fine-grained tokens) and on 21 April 2026 wrote that it was 'not really a vulnerability in the conventional sense' but true of 'any tools that enable lethal trifecta' (his term for the agent-risk pattern). A proposal that the server accept issues only from users with push access was raised in the tracker (issue #427, per DevClass)
  • 2026-10-20: Fields: evidence scope: confidence. Found in the editor's source re-check of 19-20 october 2026: single unverified reporter; the reproduction's independence is not established.
    Show the change
    Before: high
    After: medium
  • 2026-10-20: Fields: evidence scope: assertion type. Found in the editor's source re-check of 19-20 october 2026: the claim is the issue author's own account, not a record by the responsible company or an established independent reproduction (runbook rule 2).
    Show the change
    Before: fact
    After: assertion
  • 2026-10-20: Fields: evidence scope. Found in the editor's source re-check of 19-20 october 2026: issue #844 is a report by its author ('i reproduced the issue'; 'the token with only permission to public repositories did read the private repositories but not write information from them'); nothing in the record establishes who the author is or their independence.
    Show the change
    Before: In the reproduction, a token limited to public repositories could still read private repositories but did not write their contents out; the full leak needed the broad token
    After: The author of issue #844 reports that a token limited to public repositories still read the private repositories but did not write their contents out, and that the full leak needed the broad-scope token; the reproduction's independence from the researchers is not established
  • 2026-10-20: Fields: envelope authority: source ids. Found in the editor's source re-check of 19-20 october 2026: the primary record (invariant labs) makes the architectural claim; the press summary only repeats it (runbook rule 15).
    Show the change
    Before: ["DEVCLASS"]
    After: ["INV", "DEVCLASS"]
  • 2026-10-20: Fields: envelope authority. Found in the editor's source re-check of 19-20 october 2026: wording aligned to the primary record: invariant labs, 'this is not a flaw in the github mcp server code itself, but rather a fundamental architectural issue'; devclass, 'configured with permission for the private repositories'.
    Show the change
    Before: The agent's token had access to the user's private repositories as well as the public one; the researchers called this an architectural issue rather than a code flaw
    After: The agent was connected to the user's account with permission for the private repositories as well as the public one; the researchers call this a fundamental architectural issue, not a flaw in the server's code
  • 2026-10-20: Fields: decision. Found in the editor's source re-check of 19-20 october 2026: invariant labs says the agent 'pulls private repository data into context' and exfiltrated 'several pieces of private information', naming the repository, the relocation plan and the salary; it does not say whole repository contents were published.
    Show the change
    Before: The agent followed the injected instruction to read the user's other repositories and publish their contents
    After: The agent followed the injected instruction, pulled private-repository data into its context and wrote pieces of it (the name of a private repository, 'Jupiter Star', a plan to relocate to South America, and a salary) into a pull request on the public repository
  • 2026-10-20: Fields: actor. Found in the editor's source re-check of 19-20 october 2026: invariant labs: 'the user merely prompts claude 4 opus'; 'our experiments focused on claude desktop, the vulnerability is not specific to any particular agent or mcp client'.
    Show the change
    Before: A coding agent connected to the GitHub MCP server
    After: Claude Desktop (a general MCP client, not specifically a coding agent) running Claude 4 Opus, connected to the GitHub MCP server; the researchers say the flaw is not specific to any agent or MCP client
  • 2026-10-20: Context: autonomy level text. Found in the editor's source re-check of 19-20 october 2026: invariant labs: 'claude desktop by default requires the user to confirm individual tool calls. however, many users already opt for an "always allow" confirmation policy'; neither the post nor issue #844 says which setting its run used.
    Show the change
    Before: Machine acts, human supervises (approval prompts present but often set to always allow)
    After: Machine acts, human supervises (Claude Desktop asks the user to confirm each tool call by default; the researchers say many users choose Always Allow; neither run records which setting was in force)
  • 2026-10-20: Context: domain. Found in the editor's source re-check of 19-20 october 2026: the invariant labs post says the user 'is using an mcp client like claude desktop' and the demonstration ran on claude desktop with claude 4 opus.
    Show the change
    Before: Software agent (coding agent with repository tools)
    After: Software agent (an MCP client with repository tools)
  • 2026-10-20: Title. Found in the editor's source re-check of 19-20 october 2026: the invariant labs post describes 'a user's agent' and demonstrates with claude desktop, a general mcp client; 'coding agent' was the register's label, not the source's.
    Show the change
    Before: GitHub MCP server: a public issue hijacks a coding agent into leaking private-repository data, disclosed 26 May 2025
    After: GitHub MCP server: a public issue hijacks a user's agent into leaking private-repository data, disclosed 26 May 2025
  • 2026-10-16: Controls: c-o1. Found in an outside review of the published record on 16 october 2026: the record has no disclosure to the vendor before publication, so a coordinated disclosure cannot be credited.
    Show the change
    Before: succeeded: Responsible disclosure
    After: not counted: C-O1 (coordinated disclosure): not evidenced; the record shows public disclosure by the researchers but no report to GitHub before publication
  • 2026-10-13: Fields. Independent check against the linked records before right-of-reply letters.
    Show the change
    Before: developer asked to 'check and fix' issues; maintainers' response paraphrased
    After: request as the researchers quote it; maintainer's response in his own terms; push-access proposal attributed
  • 2026-10-13: Fields and sources. Claims aligned to what each linked record says, found on review.
    Show the change
    Before: 'independent reproduction by a third party'; 'responsible disclosure'; 'affects any agent regardless of model' cited to the reproduction; push-access filter as a researcher proposal
    After: reproduction described as posted, independence not established; disclosure wording as the record shows; claims attributed to the researchers and to the reproduction separately; maintainers' response recorded
Record history · 6 entries
  • 2026-10-28: No statement from GitHub within 14 days of the offer.
  • 2026-10-20: Source added: The GitHub MCP Server adds support for tool-specific configuration, and more.
  • 2026-10-20: Source added: GH-844.date.
  • 2026-10-16: Interpretation reworded for readers before sign-off; its meaning is unchanged.
  • 2026-10-14: Right of reply offered to GitHub.
  • 2026-10-14: Checked by the editor against the linked records.

Controls that address what went wrong

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

Retrieved content as data
Retrieved issue text treated as instruction
Absent · Inputs layer
Least-privilege credential scoped to task
Per-task token scoping
Absent · Envelope layer
Containment and isolation
Absent: No limit on where the agent could send what it read: it was connected with permission for the private repositories as well as the public one, and it wrote private-repository data into a public pull request. No approval prompt is recorded stopping it: Claude Desktop, used in the researchers' run, confirms individual tool calls by default, though the researchers say many users choose Always Allow, and they do not say which setting their run used. the author of the reproduction posted in issue #844 writes that there is human-in-the-loop verification, a 'Continue' button with a 'See More' preview of what the click will do.
Absent · Envelope 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 asking the agent to look at the open issues in a public repository. The task: Review issues in one public repository.
ActorWhat acted
Claude Desktop (a general MCP client, not specifically a coding agent) running Claude 4 Opus, connected to the GitHub MCP server; the researchers say the flaw is not specific to any agent or MCP client
InputsWhat it could see
A malicious issue on the public repository containing a prompt injection, which by standard GitHub rules an attacker can create
DecisionHow it chose
The agent followed the injected instruction, pulled private-repository data into its context and wrote pieces of it (the name of a private repository, 'Jupiter Star', a plan to relocate to South America, and a salary) into a pull request on the public repository
EnvelopeWhat it was allowed to do
Authority it held: The agent was connected to the user's account with permission for the private repositories as well as the public one; the researchers call this a fundamental architectural issue, not a flaw in the server's code.
ActionWhat it did
In the researchers' demonstration, the agent leaked private-repository data into a public pull request
OutcomeWhat happened
Caught first by researchers. Severity: none (demonstration).
EvidenceWhat can be proven
Record of the event: A reproduction posted as an issue on the server's own repository, using both OAuth and personal access tokens on otherwise blank repositories. Causality: The researchers assess that it affects any agent using the server, regardless of the underlying model. Scope: The author of issue #844 reports that a token limited to public repositories still read the private repositories but did not write their contents out, and that the full leak needed the broad-scope token; the reproduction's independence from the researchers is not established.
RecoveryWhat could be stopped, undone, answered for
Technical recovery: On 10 December 2025 GitHub shipped an opt-in 'lockdown mode' for its MCP server, enabled by a request header, which surfaces only content from collaborators with push access on public repositories (private repositories are unaffected), and said content sanitization against prompt injection is on by default. On the server's issue tracker a GitHub maintainer listed mitigations on 20 April 2026 (lockdown mode, read-only mode, secret scanning on public-repository calls, OAuth 2.1, strict fine-grained tokens) and on 21 April 2026 wrote that it was 'not really a vulnerability in the conventional sense' but true of 'any tools that enable lethal trifecta' (his term for the agent-risk pattern). A proposal that the server accept issues only from users with push access was raised in the tracker (issue #427, per DevClass). Accountability: The researchers published on 26 May 2025; the sources record no disclosure to GitHub before publication and no regulator action. On the server's tracker a question whether a CVE (a public vulnerability identifier) was issued went unanswered, and a GitHub maintainer wrote on 21 April 2026 that the report 'was reviewed' but was 'not really a vulnerability in the conventional sense'.

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
Retrieved content as dataEchoLeak 2025, Claude Code [bot] trust 2026, Perplexity Comet 2025Gemini calendar invite 2025 (software acting on machines)
Least-privilege credential scoped to taskPocketOS 2026, Claude Code [bot] trust 2026, Perplexity Comet 2025, Pydantic AI: a web page can make a…·
Containment and isolationOpenAI agent, Medicare portal 2026, OpenAI agents, Hugging Face 2026, EchoLeak 2025Triton 2017 (machines)

Cost and accountability

Severitynone (demonstration)
AffectedNot recorded
Costnone
Regulatory or legal consequencenone
Technical recoveryTechnical recovery: On 10 December 2025 GitHub shipped an opt-in 'lockdown mode' for its MCP server, enabled by a request header, which surfaces only content from collaborators with push access on public repositories (private repositories are unaffected), and said content sanitization against prompt injection is on by default. On the server's issue tracker a GitHub maintainer listed mitigations on 20 April 2026 (lockdown mode, read-only mode, secret scanning on public-repository calls, OAuth 2.1, strict fine-grained tokens) and on 21 April 2026 wrote that it was 'not really a vulnerability in the conventional sense' but true of 'any tools that enable lethal trifecta' (his term for the agent-risk pattern). A proposal that the server accept issues only from users with push access was raised in the tracker (issue #427, per DevClass).
AccountabilityThe researchers published on 26 May 2025; the sources record no disclosure to GitHub before publication and no regulator action. On the server's tracker a question whether a CVE (a public vulnerability identifier) was issued went unanswered, and a GitHub maintainer wrote on 21 April 2026 that the report 'was reviewed' but was 'not really a vulnerability in the conventional sense'
InterpretationWhy it matters beyond its domain. The injected issue text was the trigger; the agent's access to the user's private repositories as well as the public one is what gave the injection something to leak. The researchers call it critical to limit the agent to the repositories it needs, say traditional token-based permissions offer some protection, and give a one-repository-per-session rule as an example policy for their own Guardrails product, but the posted reproduction reports that a token limited to public repositories still read private repositories, though it did not write their contents out, so the record does not settle how far token scoping alone would have prevented the leak. The record also does not show which approval setting was in force in the researchers' run (the author of the posted reproduction writes that there is human-in-the-loop verification, a 'Continue' button with a 'See More' preview of what the click will do), and shows no attack outside the demonstrations. Signed by Saurabh Bhatnagar on 2026-10-22.

Right of reply

Named partyStatus
GitHubOffered 2026-10-14; no statement as of 2026-10-28Respond for GitHub

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?