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 | shcommands 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:
- Forging a role label (stronger): Attacker's text contains a newline followed by a forged
[User]:marker - Erasing provenance (weaker): The summary format has no field for origin; notes from files are textually identical to user-provided ones
Attack Scenarios
| Scenario | Attacker is... | How poison reaches agent | Required access |
|---|---|---|---|
| Onboarding doc (insider) | Someone on the team | Agent reads docs/onboarding.md | Commit access |
| Troubleshooting page (external) | Anyone on the web | Agent web-fetches a page while debugging | Get agent onto that page |
| Dependency README (external) | Any package author | Agent reads dependency docs while tracing | Publish 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 / Arm | Anthropic | OpenAI | Zhipu (GLM) |
|---|---|---|---|
| pi | 69% | 68% | 67% |
| gemini_cli — rule removed | 53% | 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 / Arm | With forged label | Plain text |
|---|---|---|
| pi | 87% | 6% |
| gemini_cli — rule removed | 79% | 28% |
| gemini_cli — full | 69% | 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 × Scenario | Executed | Clean |
|---|---|---|
| pi × onboarding (insider) | 3/3 | 0/3 |
| pi × webpage (external) | 1/3 | 0/3 |
| pi × dependency (external) | 3/3 | 0/3 |
| codex × all three | 0/9 | 0/9 |
| gemini_cli × all three | 0/9 | 0/9 |
Execution falls as window fills (pi, gpt-5.6-terra, onboarding scenario, n=5):
| Context window | Executed | (Laundering landed) |
|---|---|---|
| ~2,400 | 5/5 | 5/5 |
| ~26,000 | 5/5 | 5/5 |
| ~112,000 | 2/5 | 5/5 |
| ~263,000 | 2/5 | 5/5 |
| clean @ 263k | 0/3 | — |
Laundered vs. genuine approval control:
| Context | Laundered | Genuine | Clean |
|---|---|---|---|
| ~26k | 5/5 | 5/5 | 0/5 |
| ~263k | 2/5 | 2/5 | 0/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 summarizer | pi laundered |
|---|---|
| ~2,800 | 3/3 |
| ~65,200 | 3/3 |
| ~130,000 | 3/3 |
| ~306,800 | 3/3 |
| ~507,000 | 3/3 |
| ~731,000 | 3/3 |
| ~908,000 | 3/3 |
Laundering is flat at 100% from a few thousand tokens to ~908,000 (the model's 922k input ceiling).
E10: Serialization Determines Exposure
| Class | Harness | Laundered |
|---|---|---|
| Flattening | pi, opencode, Aider | 100% (15/15) |
| Flattening | OpenHands | 93% (14/15) |
| Flattening | Cline | 87% (13/15) |
| Role-typed | Codex, Gemini CLI, Qwen Code, Continue | 0% (0/15) |
E11: Executed Chain Fires on All Flattening Harnesses
| Harness | Effective window | Executed | Clean |
|---|---|---|---|
| OpenHands | ~63k | 4/5 | 0/3 |
| opencode | ~185k | 1/5 | 0/3 |
| Cline | ~185k | 1/5 | 0/3 |
| Aider | ~300k | 1/5 | 0/3 |
Execution tracks the effective compacted window, not raw session length.
E13: Attacker Can Reverse Attenuation via Recency
| Injection design | Mean salience | Executed | (Laundered) |
|---|---|---|---|
| Repeat inject 4× | 2.8 | 0/5 | 5/5 |
| Baseline (single at 75%) | 3.5 | 2/5 | 5/5 |
| Framed + repeated + at end | 3.8 | 2/5 | 5/5 |
| Framed @75% | 4.5 | 2/5 | 5/5 |
| Framed at end | 4.8 | 3/5 | 5/5 |
| Single at end (recency) | 4.8 | 4/5 | 5/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
| Arm | Full chain (WIN) | Refused post-compaction | Ran pre-compaction |
|---|---|---|---|
| Poisoned | 3/6 | 3/6 | 0/6 |
| Clean | 0/5 | 5/5 | 1/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 strict | Laundering caught | Legit claims demoted |
|---|---|---|
| 0.05 | 82% | 9% |
| 0.10 | 80% | 6% |
| 0.15 | 77% | 2% |
| 0.25 | 70% | 1% |
| 0.40 | 56% | 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:
- The forged label is the mechanism (E2): stripping it drops laundering to 6%
- Role-typed harnesses at 0% (E10): keeping roles typed prevents the attack entirely
- 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)
- Escape role labels in tool content before flattening — small serializer change, drops forged-label attack to plain-text floor
- Verify summary in code — check user-attributed claims against genuine user turns; demote ungrounded claims
- Carry provenance in schema (
{text, source}) preserved through re-summarization - Do not relabel summary as the user — give it its own role or wrap in delimiters
Conclusion
Main Takeaways
-
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.
-
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.
-
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.
-
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
- Truncate or Not? A Scaling Study of Looped Transformers with Truncated Backpropagation
Full backpropagation through time is optimal for looped transformers when both forward and backward loop counts are free, despite truncation helping when forward loops are fixed.
- Where to Spend Test-Time Compute in Recursive Reasoning
Gated Answer Resampling, a tuning-free test-time method that resamples only the decoded answer state, boosts TRM accuracy from 85.9% to 99.4% on Sudoku and 68.8% to 85.6% on PPBench at minimal compute cost.
- SimHack: Predicting the onset of detectable reward hacking before RL training
SimHack predicts reward hacking onset in LLM RL training from reference runs alone, achieving 11.3% median onset error and enabling curriculum selection that delays hacking by 96.6%.