Summary (Overview)

  • Core contribution: This paper introduces and formalizes "approval laundering" — a security failure where a durable approval record faithfully identifies an entry invocation (e.g., a command or tool call) but omits effects exercised by the transitive workflow that invocation activates (e.g., lifecycle hooks, network calls).
  • Formal framework: The authors define closure-bound approval over six operational effect classes (process, file, environment, network, container, MCP) and prove a fundamental information limit: no deterministic or randomized record-only policy can guarantee correct decisions when identical policy-visible fields require different effect-specific decisions.
  • Empirical benchmark: The Approval-to-Action Security Benchmark binds captured approval objects to immutable post-execution evidence across 111 approval-object/trace pairs, showing residual records fall from 40 (explicit fields) to 17 (command semantics) to 13 (metadata-aware view).
  • Prospective recovery: A frozen, source-backed predictor achieves 0.926 macro recall and 0.941 macro precision on a prespecified holdout, reducing residual effect instances from 10 to 3 when bound into effect-bound records.
  • Practical integration: A proof-of-concept with Claude Code's PreToolUse hook demonstrates the effect-bound record can be carried through an existing product permission path without automatic approval.

Introduction and Theoretical Foundation

The paper addresses a critical gap in coding-agent security. Approval interfaces (e.g., Claude Code, GitHub Copilot CLI, Qwen Code) ask humans to authorize commands or tool calls, but the durable record of that approval names only the entry invocation, while developer tools execute a transitive workflow that invocation activates.

Key motivating examples:

  • A Vite project install command (pinned to fixed SHA) invoked postinstall and wrote a workspace file — the record showed only "process" but the workflow also exercised "file" effects.
  • An MCP documentation-tool call exercised both the represented MCP capability and network authority — the record omitted the "network" effect.

The authors define approval laundering as:

"a durable record faithfully identifies the entry invocation but leaves at least one effect of its transitive workflow unbound. The invocation is truthful; the authority it activates is incompletely represented."

Research questions:

  • RQ1: How does approval-record coverage change across explicit-field, command-aware, and metadata-aware views?
  • RQ2: Does the gap recur in fixed-SHA public-project workflows and across coding-agent frontends?
  • RQ3: Can decision-time metadata predict and bind missing effects before execution?

Methodology

Formal Framework

The paper formalizes the approval transaction with these components:

  • Approval surface: Information available to the decision-maker
  • Base context b0∈B0b_0 \in \mathcal{B}_0: Committed before any adapter response
  • Routing outcome h∈Hh \in H: e.g., ASK, pass-through, or local denial
  • Bound decision context b=⟨b0,h⟩∈Bb = \langle b_0, h \rangle \in B
  • Policy-visible projection I(b)∈TI(b) \in \mathcal{T}: The complete decision-time input
  • Record-only policy F:T→Δ(D)F: \mathcal{T} \to \Delta(\mathcal{D}): A possibly randomized decision rule
  • Sealed record p=Seal(b,d)p = \text{Seal}(b, d): The durable pre-execution record

Closure-bound approval (Definition 1):

∀τ∈CΓ(a,m,s0):Eff⁡Ω(τ)⊆Rep⁡Ω(p).(1)\forall \tau \in C_{\Gamma}(a, m, s_0): \operatorname{Eff}_{\Omega}(\tau) \subseteq \operatorname{Rep}_{\Omega}(p).\tag{1}

Coverage gap predicate (Definition 2):

Gap⁡Ω(b,τ)  ⟺  Eff⁡Ω(τ)⊈Rep⁡Ω(b).(2)\operatorname{Gap}_{\Omega}(b, \tau) \iff \operatorname{Eff}_{\Omega}(\tau) \not\subseteq \operatorname{Rep}_{\Omega}(b).\tag{2}

Information limit (Lemma 1) — Record-only policy indistinguishability:

I(B(p1))=I(B(p2)),q1≠q2,  ⟹  F(I(B(p1)))=F(I(B(p2)))=:μ,(3)\begin{array}{c} I(B(p_1)) = I(B(p_2)), \qquad q_1 \neq q_2, \\ \implies \quad F(I(B(p_1))) = F(I(B(p_2))) =: \mu, \end{array}\tag{3}

and FF cannot agree with QQ almost surely on both instances.

Six-Class Operational Vocabulary

The experiments instantiate Ω6\Omega_6: process, file, environment, network, container, MCP.

Benchmark Design

  • Ledger: 149 attempts, 139 SUCCESS, 111 canonical deduplicated records
  • Three information views:
Avail6explicit=Rep6(b),Avail6command=Rep6(b)∪Cmd6(a;Γ),Avail6metadata=Rep6(b)∪Pred6(a,m,s0).(4)\begin{array}{r} \mathrm{Avail}_6^{\mathrm{explicit}} = \mathrm{Rep}_6(b), \\ \mathrm{Avail}_6^{\mathrm{command}} = \mathrm{Rep}_6(b) \cup \mathrm{Cmd}_6(a; \Gamma), \\ \mathrm{Avail}_6^{\mathrm{metadata}} = \mathrm{Rep}_6(b) \cup \mathrm{Pred}_6(a, m, s_0). \end{array}\tag{4}

Prospective Protocol

  • Parser v1.0 frozen before controlled cohort; v1.1 developed from Natural-A errors, then frozen before confirmatory cohort B
  • 18 prespecified workflows from 18 unseen fixed-SHA repositories
  • 17 reach target execution; 13 complete successfully, 4 terminate with effect evidence

Empirical Validation / Results

RQ1: Approval-Record Coverage

Finding 1: Explicit approval fields omit observed effect classes in every benchmark mechanism class — 40 of 111 canonical records have a nonempty residual.

Finding 2: Command semantics resolve 23 of 40 residual records; metadata resolves 4 more — residuals fall from 40 → 17 → 13.

RQ2: Fixed-SHA Recurrence

Finding 3: Across 11 evidence-complete executions of 8 fixed-SHA repository cases, residual records fall from 10 → 2 → 0 across the three views.

Finding 4: Two exact mappings recur across three product frontends (Claude Code, GitHub Copilot CLI, Qwen Code):

  • Vite: P → P,F (process → process + file)
  • MCP: M → M,N (MCP → MCP + network)

Table II: Per-case residual records across 11 fixed-SHA runs

Case and short SHARunsExplicitCommandMetadataMechanism / sourceRepresented → observed
webpack/webpack@efeb5ce21100npm lifecycle / package.jsonP → P,F
vitejs/vite@64dfee122200npm lifecycle / package.jsonP → P,F
pypa/pip@72e6c5941100PEP 517 / pyproject.tomlP → P,F
pallets/flask@36e4a8241100PEP 517 / examples/celery/pyproject.tomlP → P,F
BurntSushi/ripgrep@dfe4a81d1100Cargo build script / build.rsP → P,F
microsoft/vscode@8d5908d61100Docker build / .devcontainer/DockerfileP → P,F,C
docker/awesome-compose@30f4b7f61100Docker build / angular/angular/DockerfileP → P,F,C
modelcontextprotocol/servers@7b1170d11000MCP client configuration / .mcp.jsonM → ∅ (strict)
same fixed-SHA case2220MCP remote calls / client .mcp.jsonM → M,N
Total1110208 fixed-SHA cases across five mechanism families

RQ3: Pre-Execution Recovery

Finding 5: Frozen metadata improves prospective recovery on the paired holdout:

  • Macro recall: 0.770 → 0.926
  • Macro precision: 0.941 (unchanged)
  • Exact-set matches: 9/17 → 13/17 (four repairs, zero regressions)

Finding 6: Effect-bound records disclose seven additional effect instances.

Table III: Confirmatory-B disclosure and routing by stratum

ScopeCoverage Cmd.→EBResidual Cmd.→EBExact sets Cmd.→EBASK protocolNo-added-effect ASK
Overall.755→.92210→39/17→13/1717/189/17
Positive.676→.9728→14/9→8/99/94/9
Controls.857→.8572→25/8→5/88/95/8

Effect-Bound Record Construction

The effect-bound record seals the complete predicted set:

pEB=Seal⁡(bEB,d),Rep⁡6(pEB)=E^6=Pred⁡6(a,m,s0).(5)\begin{array}{c} p_{\mathrm{EB}} = \operatorname{Seal}(b_{\mathrm{EB}}, d), \\ \operatorname{Rep}_6(p_{\mathrm{EB}}) = \widehat{E}_6 = \operatorname{Pred}_6(a, m, s_0). \end{array}\tag{5}

Performance metrics: Parser predictions are stable with worst same-process P95 of 12.3 ms; fresh-process maximum P95 is 168.2 ms. The Claude Code hook integration (100 in-process preflights) has P95 of 1.51 ms; 30 fresh hook processes have median 87.8 ms and P95 98.1 ms.

Theoretical and Practical Implications

Security Implication

Closure-bound approval separates effect coverage from invocation identity. A truthfully identified invocation is insufficient when the decision-time approval object omits effects activated by its workflow. The record-only indistinguishability result (Lemma 1) proves that when an omitted effect changes the required decision, a policy restricted to unchanged visible fields cannot recover that distinction.

Bind–Enforce–Contain Architecture

The paper proposes a forward-only chain:

  1. Bind: Derive source-backed predictions from workflow-expansion sources; commit the frozen effect set and provenance to bb before authorization.
  2. Enforce: Evaluate product policy over I(b)I(b) to produce dd; the completed record p=Seal(b,d)p = \text{Seal}(b, d) preserves both.
  3. Contain: Restrict execution to the effect boundary recorded in B(p)B(p).
  4. Audit: Append artifact-bound observations to form p+p^+, comparing realized effects with the frozen prediction.

Generalization

The relation extends beyond coding agents to any system with an effect vocabulary, inspectable decision-time expansion sources, activation evidence, and post-execution effect evidence — including browser, SaaS/API, and nested-agent systems.

Design Principle

"Bind the effect boundary before the decision, enforce from the bound record, and contain execution to that boundary."

Conclusion

Approval laundering is a record-to-closure security failure: a durable record faithfully identifies an entry invocation yet omits effects activated by its selected implementation. The paper presents the first systematic analysis of this relation across controlled mechanisms, fixed-SHA projects, and product frontends.

Key takeaways:

  1. The information limit is fundamental — no record-only policy can guarantee correctness when identical policy-visible inputs require different effect-specific decisions.
  2. The gap is measurable and recurrent — across all nine mechanism classes, eight fixed-SHA cases, and three product frontends.
  3. Prospective recovery works — frozen, source-backed predictions achieve high precision/recall and reduce residual effects by 70% (10 → 3).
  4. The repair is practical — effect-bound records integrate with existing product approval paths (Claude Code PreToolUse hook) at acceptable latency.

Future directions: Authorization should bind the invocation, predicted transitive effect boundary, and provenance before deciding, preserving that commitment through execution and audit. The paper also notes deployment responsibility concerns: incomplete predictions could create false assurance, over-broad ASK routing could cause approval fatigue, and durable records could expose sensitive metadata — suggesting staged, reversible deployment with rollback triggers.

Related papers