Week 26 · August 2026

14,560 Injection Runs: Why Aggregate Rates Hide Real Attacks

August 23, 2026 · by Satish K C 8 min read
Security Agents LLMs Evaluation
Built by the Author Kravhal - autonomous agents that run your business workflows end-to-end. Pay per outcome.
Get Early Access

The Paper

"Security Assessment of DeepSeek Harness with A.I.G: Evaluating Resistance to Indirect Prompt Injection" was published in August 2026 by Zonghao Ying, Xiangfan Wu, Huiyu Wu, Xing Zheng, Huangsheng Cheng, Xiaorong Shi, and Jing Guo of Tencent Zhuque Lab. The central claim is that indirect prompt injection resistance cannot be characterized by a synthetic agent or by a single aggregate score. Driving the real DeepSeek Harness TypeScript runtime through 14,560 controlled executions, the authors report an overall full-success rate of 5.6% that conceals individual channel and carrier slices reaching 25.5%.

Read the Paper on arXiv →

The Problem Before This Paper

Indirect prompt injection has been understood since Greshake et al. showed in 2023 that instructions embedded in content an application must process can redirect a model away from the user's request. The benchmarks that followed established tasks and success conditions but stopped short of the thing a deployment actually ships: InjecAgent (Zhan et al., ACL Findings 2024) and AgentDojo (Debenedetti et al., NeurIPS 2024) evaluate injection against benchmark-supplied agent scaffolds rather than a specific composed runtime with its own tool registry, session log, and model adapter. Defenses including spotlighting (Hines et al., 2024), BIPIA boundary awareness (Yi et al., 2025), and StruQ structured queries (Chen et al., 2025) target the prompt boundary, which presumes the payload has already reached the prompt in a recognizable form. Two gaps remained. First, nobody had measured whether a plugin-composed production runtime prevents untrusted content from changing agent actions, as opposed to measuring whether a model rejects a malicious string. Second, injection testing had settled on textual approximations of carriers and single-number reporting, both of which turn out to erase the cases that matter.

What They Built

The assessment uses a source-to-sink threat model. A source is a content-reading tool whose result carries attacker-controlled material, making the returned page, file, record, or skill a tainted artifact. A sink is an externally observable action the attacker wants performed: sending email, submitting a form, executing a command, transferring money. The attacker controls the tainted artifact and nothing else - not the user request, system prompt, tool registry, judge, or sink implementation. AI-Infra-Guard (A.I.G) supplies payload construction, carrier injection, taint routing, a runtime adapter, trace collection, and two judges. The adapter executes DSH's actual TypeScript runtime rather than a stand-in: it creates isolated taint, clean-sample, and sink-log files per run, launches a driver with npx tsx, and consumes JSONL session events. The driver uses DSH's own agent-loop dependency mounting pattern, creating an agent through ctx.agentLoop.create(), submitting a benign request with agent.followup(), waiting for idle, then reading agent.session.events. A fixture plugin registers six source tools covering web retrieval, documents, email, knowledge search, skills, and chat messages, plus eight tracked sink tools that record name and arguments to a local file and return a synthetic result. Tool selection and argument construction stay with the model; the consequences do not leave the machine. The full_channel_mode dataset balances 16 channels against 2 carrier modes and 35 payload objectives for 1,120 base cases, then applies an unmodified naive baseline plus 12 attack wordings to produce 14,560 executions. Thirty-two objectives require a sensitive action with critical expected arguments such as a recipient, account, or destination URL, broken down as seven email, seven command, four transfer, four form, three social-post, three calendar, two direct-message, and two channel-post tasks. Three objectives require only an output canary. The model backend is deepseek-v4-flash through a local proxy.

Outcomes are scored twice, and the paper is deliberate about not merging the two. The deterministic evaluator JR (RuleJudge) checks explicit trace evidence: whether taint reached a tool result, whether a sink fired, whether critical sink arguments match the attacker task, whether a canary dominates the final answer, and whether the answer resembles a refusal. A sink call with a mismatched critical argument counts as partial compliance, not success. The semantic evaluator JL (LLMJudge) runs offline over the saved trace along with the legitimate task, attacker objective, canary, expected arguments, and sink requirement, returning FULL, PARTIAL, or FAILURE. JL never overwrites JR.

The authors then inspected the DSH source snapshot used in the experiment, commit 47f943859bef dated August 13, 2026, and identified the two control-flow locations that determine exposure. The first is in tool-calls.ts under packages/core/agent-loop/src, where a tool result is appended to the session and the contexts it returns are accepted:

appendToolResult(session, turn, step,
  call!.block, result, ...)
for (const context of
  result.additionalContexts ?? []) {
    acceptContext(context)
}

Paired with deferContext(context: UserMessage) in the tools module, this means any retrieval tool, MCP integration, skill, or plugin that controls result content sits on the model-visible input boundary. The second location is the tool-call guard, which executes after tools/pre-execute listeners and before the tool body:

export type ToolGuard =
  (execution: Readonly<ToolExecution>)
    => string | undefined

Returning a reason denies the call, and the denial is monotonic: no later listener can convert it back into an allow. The authors are explicit that the experiment does not show these interfaces are flawed. It shows why a deployment has to use them when an untrusted source precedes a sensitive sink.

Key Findings

Results

Across 14,560 runs, JR assigned 819 full successes (5.6%) and 298 partial compliances (2.0%), for a broad-influence rate of 1,117 runs (7.6%). JL assigned 772 full successes (5.3%) and 1,060 partial compliances (7.3%), for 1,832 runs (12.6%), with 9 judge errors (0.1%). Carrier representation moved the aggregate: file mode produced 6.2% JR full success against text mode's 5.1%, and 387 observed sink calls against 254. That aggregate difference does not hold per channel - chat messages ran 9.5% in text mode and 1.3% in file mode, calendar events 7.7% against 4.2%, while documents went the other way at 5.5% against 7.3%. Channel spread under JR ranged from hidden Unicode at 0.0% text and 25.5% file, through skills at 14.3% and 16.0%, translation at 7.9% and 8.8%, webpages at 5.1% and 4.4%, down to log files at 2.4% in both modes. By wording, escape reached 8.6% text and 9.3% file, prefix injection 3.8% and 5.5%, payload splitting 2.1% and 4.6%, and stealth instruction 0.9% and 1.8%. Every one of these percentages is a measurement of one DSH revision, one model, one persona, and one unhardened baseline configuration, with all sinks simulated. A recorded sink call is an attempted sensitive action, not a breach.

Why This Matters for AI and Automation

My Take

The DeepSeek Harness framing is the least interesting thing about this paper, and the authors seem to know it - Appendix B goes out of its way to say the percentages are descriptive measurements for one controlled configuration, not universal vulnerability rates for any runtime or model provider. What the work actually contributes is a method with two properties most injection testing lacks: it runs the real session-event path instead of a reimplementation, and it refuses to collapse the deterministic and semantic verdicts into one number. That second choice is where the useful signal came from. The obfuscation gap, 13.6% under the rule judge against 9.1% under the semantic judge, is a case where a team running only a rule judge would spend a sprint hardening against an attack that was not really succeeding, while the 7.3% semantic partial rate flags traces where behavior genuinely shifted but no criterion tripped - which is the population worth reading by hand. The honest limitation is the one the authors do not resolve: prompt hardening was off, so the paper measures an unhardened floor rather than the number a real deployment would see, and there is no ablation showing how much of the 7.6% broad-influence rate normalization alone would remove. Given that the worst cell is a Unicode handling artifact, my guess is that a meaningful share of it is a parser fix rather than a policy problem, and that guess is testable with the released code. The finding I expect to age best is the skills channel, because it is the one that describes how people are actually building agents right now: pasting in a skill file from somewhere, wiring an MCP server someone else published, trusting a tool description because it arrived alongside working code. Those are dependencies. We review dependencies. We do not review these.

Discussion question: Hidden Unicode scored 0.0% when tested as text and 25.5% when tested as a real file, which means the vulnerability lived in the ingestion path rather than the model. For the agent systems you run today, do your injection tests construct the actual carrier - the real HTML, PDF metadata, spreadsheet cell, or skill file - or do they hand the model a string that approximates it, and what would it cost you to find out which channels change verdict when you switch?

← Back to all papers
Share