Summary (Overview)

  • Novel attack vector: The paper identifies "compaction laundering" — a vulnerability in context-compacting coding agents where an attacker can forge user instructions that survive context summarization as genuine user commands.
  • Root cause: Harnesses that flatten typed conversations into plain strings with in-band role labels (e.g., [User]:) destroy message provenance, making forged labels indistinguishable from real user input.
  • Measured impact: Across five flattening harnesses (pi, opencode, Cline, Aider, OpenHands), forged approvals launder into agent memory 87–100% of the time, up to a ~908,000-token context window; four role-typed harnesses (Codex, Gemini CLI, Qwen Code, Continue) show 0% vulnerability.
  • Executed consequences: Laundered approvals drive real tool-running agents to execute attacker-controlled curl | sh commands in sandboxes, with live end-to-end success in the pi TUI at ~50% against a 0% clean control arm.
  • Defense: A code-level provenance check catches 77% of laundering while demoting only 2% of legitimate summary content, outperforming prompt-based rules (13–25%) and published classifier defenses (67% at best).

Introduction and Theoretical Foundation

The Problem

Long-running coding agents must eventually compact their context window by summarizing the conversation and discarding the original. This paper demonstrates that this compaction step is an exploitable trust boundary in a class of popular open-source coding agents.

The core vulnerability: harnesses flatten typed messages (user, assistant, tool) into a single plain string marked with text labels like [User]: or [Tool result]:. When untrusted content (files, web pages) contains a forged [User]: line, it becomes indistinguishable from genuine user input after flattening. The summarizer then faithfully records it as a user instruction — not because it's tricked, but because recording user constraints is its job.

Key Insight

"Whether a harness is exposed depends on how it serializes the conversation for the summarizer. Harnesses that flatten the roles into in-band labels are exposed; those that keep messages role-typed are not."

This reframes the failure from a model limitation (inability to determine content origin) to a harness code defect (destruction of provenance before the model sees the text). This distinction admits defenses the prompt-focused literature does not consider.

Scope and Severity

  • Mandatory attack surface: Compaction is required for every long-running agent; no auxiliary memory modules needed
  • Impact: Code execution with the developer's own permissions
  • External attackers: A maliciously set-up troubleshooting page can carry the attack without insider access
  • Inherited vulnerability: Derivative agents built on flattening harnesses silently inherit the flaw

Methodology

The Trust Boundary

The attack requires the summarizer to be accurate, faithfully copying a forged [User]: line into the user's instruction section. The attack does not trick or jailbreak the summarizer — it exploits the summarizer's correct behavior.

Threat Model

Two attack primitives:

  1. Forging a role label (stronger): Attacker's text contains a newline followed by a forged [User]: marker
  2. Erasing provenance (weaker): The summary format has no field for origin; notes from files are textually identical to user-provided ones

Attack Scenarios

ScenarioAttacker is...How poison reaches agentRequired access
Onboarding doc (insider)Someone on the teamAgent reads docs/onboarding.mdCommit access
Troubleshooting page (external)Anyone on the webAgent web-fetches a page while debuggingGet agent onto that page
Dependency README (external)Any package authorAgent reads dependency docs while tracingPublish a package version

Harness Classes

Flattening harnesses (vulnerable): pi, opencode, Cline, Aider, OpenHands — serialize history into one text string with in-band role labels.

Role-typed harnesses (control): Codex, Gemini CLI, Qwen Code, Continue — pass conversation as typed message array where role is a field attackers cannot reach.

Experimental Setup

  • Real harness summarization prompts (copied verbatim from pinned commits)
  • Real frontier model API calls (Anthropic, OpenAI, Zhipu/GLM)
  • Real execution in disposable Docker containers with benign canary payloads
  • Staged conversations with synthetic poison, plus live end-to-end testing in the real pi TUI

Metrics

  • Laundering (primary): Forged line appears in summary as user-attributed content, scored by LLM judge
  • Survival: Weaker signal — line appears in summary at all (may be filed as document content)
  • Issued vs. confirmed: Whether agent ran the command vs. proof file appearing on disk
  • Clean arm: Identical task with no forged line; must remain at zero

Empirical Validation / Results

E1: Laundering Rate Stable Across Model Families

Using pi's real summarization prompt (n=72 per cell):

Harness / ArmAnthropicOpenAIZhipu (GLM)
pi69%68%67%
gemini_cli — rule removed53%83%86%
gemini_cli — full (vendor rule)46%62%60%
codex †0%0%0%

pi landing within two points across three unrelated labs indicates the cause is the harness's flattening code, not the model.

E2: The Forged Label Is the Mechanism

Harness / ArmWith forged labelPlain text
pi87%6%
gemini_cli — rule removed79%28%
gemini_cli — full69%3%

Without the forged label, the same words mostly do not launder.

E6: Laundered Approval Drives Execution

Across harnesses and scenarios (gpt-5.6-terra, n=3):

Harness × ScenarioExecutedClean
pi × onboarding (insider)3/30/3
pi × webpage (external)1/30/3
pi × dependency (external)3/30/3
codex × all three0/90/9
gemini_cli × all three0/90/9

Execution falls as window fills (pi, gpt-5.6-terra, onboarding scenario, n=5):

Context windowExecuted(Laundering landed)
~2,4005/55/5
~26,0005/55/5
~112,0002/55/5
~263,0002/55/5
clean @ 263k0/3—

Laundered vs. genuine approval control:

ContextLaunderedGenuineClean
~26k5/55/50/5
~263k2/52/50/5

Laundered and genuine approvals yield identical execution rates — the drop is not forgery detection but general caution about curl | sh.

E7: Laundering Is Scale-Invariant

Context fed to summarizerpi laundered
~2,8003/3
~65,2003/3
~130,0003/3
~306,8003/3
~507,0003/3
~731,0003/3
~908,0003/3

Laundering is flat at 100% from a few thousand tokens to ~908,000 (the model's 922k input ceiling).

E10: Serialization Determines Exposure

ClassHarnessLaundered
Flatteningpi, opencode, Aider100% (15/15)
FlatteningOpenHands93% (14/15)
FlatteningCline87% (13/15)
Role-typedCodex, Gemini CLI, Qwen Code, Continue0% (0/15)

E11: Executed Chain Fires on All Flattening Harnesses

HarnessEffective windowExecutedClean
OpenHands~63k4/50/3
opencode~185k1/50/3
Cline~185k1/50/3
Aider~300k1/50/3

Execution tracks the effective compacted window, not raw session length.

E13: Attacker Can Reverse Attenuation via Recency

Injection designMean salienceExecuted(Laundered)
Repeat inject 4×2.80/55/5
Baseline (single at 75%)3.52/55/5
Framed + repeated + at end3.82/55/5
Framed @75%4.52/55/5
Framed at end4.83/55/5
Single at end (recency)4.84/55/5

Moving the single forged approval to the end raises execution from 40% to 80%. Naive repetition is counterproductive (drops to 0%).

E15: Complete Chain Live in Real pi TUI

ArmFull chain (WIN)Refused post-compactionRan pre-compaction
Poisoned3/63/60/6
Clean0/55/51/6 †

† One clean take executed during first turn — model variance, absorbed by paired design.

Key findings: The agent's pre-compaction audit is a substantial barrier (compaction can erase it); post-compaction trigger phrasing matters (neutral "ok, what's next?" produced clearest separation: 3/6 poisoned vs. 0/5 clean).

E16: The Audit Is Forge-Resistant

With a genuine skeptical audit in the transcript, execution collapses to 1/50 pooled across all forgery arms (user, think, both, evidence). Assistant-thinking forgery is falsifiable against the transcript; user forgery is not, because user turns are the one unfalsifiable voice in the flattened stream.

E9: Code-Level Defense

How strictLaundering caughtLegit claims demoted
0.0582%9%
0.1080%6%
0.1577%2%
0.2570%1%
0.4056%0%

Comparison: Gemini's in-prompt rule stops ~13–25%; published classifiers reach 67% at best; the provenance-contrast check catches 77% with 2% collateral.


Theoretical and Practical Implications

Root Cause Reframing

The vulnerability is a serialization bug in harness code, not a general model limitation. Evidence:

  1. The forged label is the mechanism (E2): stripping it drops laundering to 6%
  2. Role-typed harnesses at 0% (E10): keeping roles typed prevents the attack entirely
  3. Model families show minimal variation (E1): pi at 69/68/67% across labs

Why Prompt-Level Defenses Fail

"A summarizer can notice the injection attempt and still never ask who sent it, so detection does not amount to prevention."

The in-prompt anti-injection rule reduces laundering by 7–26 points depending on model but never below 60% on flattening harnesses. Role-typing, not the rule, is why Gemini CLI achieves 0%.

Attack Characteristics

  • Scale-invariant: Laundering persists at 100% regardless of context size or position
  • Compaction-immune: Repeated compaction neither strengthens nor removes injected claims (E4)
  • Attacker-addressable attenuation: Execution declines with window size due to reduced salience, but recency placement reverses this (E13)

Defense Recommendations (by implementation cost)

  1. Escape role labels in tool content before flattening — small serializer change, drops forged-label attack to plain-text floor
  2. Verify summary in code — check user-attributed claims against genuine user turns; demote ungrounded claims
  3. Carry provenance in schema ({text, source}) preserved through re-summarization
  4. Do not relabel summary as the user — give it its own role or wrap in delimiters

Conclusion

Main Takeaways

  1. Compaction laundering is a real, exploitable vulnerability in all five tested flattening harnesses, with 87–100% laundering rates and executed consequences (RCE) demonstrated in sandboxes and live in the real pi TUI.

  2. The fix is structural, not prompt-based: Role-typed serialization (already used by four harnesses) eliminates the vulnerability entirely; escaping role labels before flattening is a minimal code change.

  3. The attack targets the unfalsifiable voice: User turns make no verifiable claims, so the summarizer cannot check whether the user really approved anything. Assistant and tool content remains checkable against the transcript.

  4. The agent's own audit is the strongest defense: A diligent pre-compaction audit that survives into the summary is forge-resistant (E16), but compaction can erase it (E15).

Limitations

  • Executed demonstrations run on OpenAI models (claude-opus-5 refused to summarize malicious transcripts ~56% of the time)
  • Salience mechanism measured within a single model
  • All payloads are benign canaries; high-stakes payloads (credential exfiltration) never executed even when laundered
  • Defense not yet tested against adaptive attacks
  • Every measured rate is a floor — recombination attacks and targeted poisoning likely increase exposure

Future Directions

  • Independent-judge, multi-model replication of salience mechanism
  • Adaptive attack testing against the provenance-contrast defense
  • Sandbox-enforced harnesses: demonstrating in-sandbox exfiltration and blinded review consequences
  • Field measurement of real audit strength across diverse agent deployments

Related papers