Skip to content
PERMISSION/PROTOCOL
Back to incident tracker

2026-09-17

HighPrimary

LangGraph Agent Server Could Reuse Approval for a Different A2A Transfer Action

A controlled LangGraph Agent Server test changed a pending transfer after review and reused the earlier approval for the modified action.

LangGraph Agent ServerGovernance bypassPost-approval state substitution in a controlled agent workflowA controlled in-memory LangGraph Agent Server composition using the shipped A2A message.command.update route and official human-in-the-loop middleware

What happened

In controlled testing, the maker changed a paused same-ID tool call from mock_wire_transfer(20, approved-vendor) to mock_wire_transfer(2000, attacker-sink), and the later approver resume executed the changed call under the earlier decision.

Why it matters

The harmless mock ledger recorded a 2,000-unit transfer to the attacker sink instead of the reviewed 20-unit transfer. No production systems, payment networks, customer data, or real funds were involved.

Missing authorization check

An exact use-time comparison between the approved canonical operation and the operation presented to the tool sink, or a policy preventing unauthorized mutation of approval-pending state.

Would PP block it?

The approval would sign the canonical 20-unit operation. After the pending state changed to 2,000 units and a different destination, the sink-side digest would no longer match the receipt and execution would fail closed or require a new approval.

Incident analysis

Timeline and technical read

Timeline

  1. 2026-09-10

    The public evidence set's experimental cutoff records strict LangGraph positives through Agent Server 0.14.0 and a safe deny-update policy control.

  2. 2026-09-17

    The Loopjacking paper is published on arXiv with the LangGraph controlled-test results.

  3. 2026-09-21

    The researcher publishes the focused LangGraph and A2A field note with requests, decisions, controls, and claim boundaries.

Technical breakdown

  • The maker could create work and update a shared pending thread but could not resume the approval interrupt or execute the protected mock transfer directly.
  • The approver read the exact 20-unit transfer view and had authority to resume and execute, but did not perform the maker's state update.
  • A later A2A message reused the pending message and tool-call IDs while replacing the tool-call arguments with a 2,000-unit transfer to another destination.
  • On approval resume, the human-in-the-loop path reconstructed the call from current thread state without comparing it with the earlier approval view, so the mock tool received the changed operation.
  • The direct-maker attempt was denied, the unchanged-operation control executed the reviewed transfer, and a deny-update policy blocked the substitution.

Authorization boundary

Where the authorization boundary should have been

This incident is categorized as Governance bypass. The relevant Permission Protocol gate is Tool-Call Gate. The read is conditional: the block only applies where the real action boundary is routed through a gate.

If enforced at
The protected transfer tool immediately before side effects are committed
Still needs
Permission Protocol does not repair LangGraph state management, prevent all shared-thread mutation, or replace correct concurrency and authorization policy. Workflows without an integrated sink-side gate remain outside coverage.
Receipt required for
Executing the exact transfer operation, including tool name, amount, destination, request identity, approver, and current state digest

A Tool-Call Gate can require a separately authenticated receipt bound to the exact operation, amount, destination, identity, and request digest before the sink executes.

Start small

Put the relevant gate at this action boundary.

This incident maps to Tool-Call Gate. Start with the boundary that controls the actual action, then require a signed receipt before execution.

Replay this incident with a signer in the loop