Fire In Belly

AI Agent Instruction Provenance: Stop Harness Role Escalation

9 min read

Three blank hanging tags in white, pale pink and black against a sage green wall

A coding agent reads a poisoned README, refuses to run the backdoor itself, then hands the same command to a subagent. The harness rebuilds that subagent's context and drops the command into a user message. The subagent runs it. Automatic permission review may allow it too, because the transcript now looks like an explicit user request. Schema checks passed. The sandbox looked fine. The failure was reconstruction: tool-origin text gained user privilege without a human.

You need an instruction provenance contract: every carried fragment keeps its origin privilege, harness reconstruction cannot elevate that privilege, and permission reviewers consume origin labels rather than trusting reconstructed message roles. It sits beside validating AI agent tool calls before execution (schema, identity, authorization), binding human approval to exact AI agent actions (the approval artifact), propagating tool-output taint before privileged AI agent actions (argument provenance after results return), verifiable egress control (network-boundary mediation and receipts), and AI agent audit logs (accountability outside model control). The job here is narrower: decide which instruction level a piece of text may claim when the harness rebuilds context.

Why message roles are a security boundary

OpenAI's Instruction Hierarchy research argues that modern agents fail when system, user, and tool text are treated as equal priority. Models are trained so system and developer instructions outrank user text, and tool outputs hold the least instruction privilege. The OpenAI Model Spec publishes that chain of command as product policy: root and system constraints bind first; developer and user instructions follow; tool content is data unless a higher layer authorizes otherwise.

That hierarchy only works when the labels the model sees match how the content entered the system. If a harness copies tool output into a user message, the model is not confused. It is doing what it was trained to do: trust user instructions more than tool text. Permission reviewers that infer "the user asked for this" from the same reconstructed transcript make the same mistake with more authority.

OWASP LLM06:2025 Excessive Agency covers the blast radius when agents get more functionality, permissions, or autonomy than the job needs. Mitigations start with fewer extensions, least privilege, complete mediation in downstream systems, logging, and rate limits. Provenance-preserving reconstruction is one form of complete mediation: the harness may not invent a higher principal for attacker-controlled text.

The attack: instruction privilege escalation

When Context Gets Root names the failure mode. Instruction privilege escalation happens when harness context reconstruction presents content at a higher model-facing level than its origin. Two common elevations:

  1. Tool-to-user. File reads, search hits, or tool results are later placed in a user message for a subagent, persistent goal, or scheduled task.
  2. Tool-to-system. Attacker-influenced text is installed into a custom subagent system prompt or skill metadata and later loaded as system-effective policy.

The paper evaluates six coding-agent harnesses across thirteen objectives that span confidentiality, integrity, availability, and remote code execution. With unrestricted execution, every objective succeeded on every harness after escalation. With automatic permission review, every objective still succeeded on the harnesses that offered that mode. Tool-level prompt injection and role-confusion baselines mostly failed on the same setups. The difference was not a smarter jailbreak. It was the harness rewriting privilege.

Promptfoo's catalog entry on agent confused-deputy escalation covers the multi-agent cousin: a low-privilege agent induces a high-privilege peer to invoke sensitive tools over natural-language channels because peers trust each other by default. That is the same family of bug: missing mandatory checks on who may authorize what, applied to agent-to-agent messaging rather than message-role reconstruction. Your contract should cover both surfaces when you ship multi-agent workflows.

Origin privilege labels

Give every context fragment an origin privilege that never upgrades casually:

Origin privilegeTypical first entryMay instruct privileged tools?
toolFile read, search, HTTP/MCP tool result, email bodyNo, unless a higher principal and policy grant say so
userAuthenticated human message in this sessionYes, within that user's authz and approval rules
system_effectiveOperator-owned system/developer policy, pinned subagent configYes, as platform policy, never as untrusted content

Store the label beside the bytes, not only in the API role field the next call happens to use. When the harness serializes a Responses or Messages payload, the API role must be less than or equal to the origin privilege. A tool fragment may appear as tool/function output. It must not appear as user or system/developer unless a deterministic policy records an explicit, audited elevation, and for attacker-controlled workspace text, that elevation should simply be forbidden.

Preserve origin privilege across harness reconstruction; a subagent user message is not human authorization if the text began as tool output. That is the first operating rule. If the label can be dropped, the hierarchy is theater.

Non-escalating reconstruction rules

Apply the same rule to every reconstruction path, not only the one your framework markets as "subagents."

Delegation and subagents

OpenAI's Codex subagents documentation describes spawning specialists whose prompts the harness assembles. When the main agent forwards a task, copy origin labels with the text. If the task body traces to tool content, present it to the subagent as tool/data context or as a clearly labeled untrusted task block that models and reviewers treat as non-authoritative. Do not mint a fresh user message that implies a human typed the payload.

Persistent goals and scheduled tasks

Goals and cron-like schedules often re-inject stored prompts as user messages on later turns. That is tool-to-user escalation with a delay. Persist origin_privilege and origin_run_id with the goal text. On replay, restore those labels. If origin is tool, the working agent and any Auto PR path must see untrusted data, not a forged user request.

Custom subagents and skills

Treat custom system prompts and skill metadata as system-effective only when an authenticated operator installed them through a controlled channel with integrity pins. Workspace files the agent can edit must not become system-effective by self-installation. If an agent proposes a new subagent definition, require the same approval and pinning path you use for production policy changes.

Treat goals, schedules, and custom subagent prompts as reconstruction surfaces with the same non-escalation rule as delegation. Teams that harden only the spawn_subagent API leave the back doors open.

Reviewers must consume origin, not theater

Automatic permission review is useful when it judges risk and user intent from a faithful transcript. It becomes an accelerator for the attack when the transcript lies about who authorized the action.

Feed automatic permission review origin labels, not only reconstructed roles; Auto PR that trusts forged user messages will approve the attack. Practical requirements:

  • Include origin_privilege and origin_refs for every instructing fragment in the review context.
  • Deny or escalate to a human when a high-risk action's authorizing text has origin tool or unknown.
  • Never treat "the user message says I know the risks" as human approval unless that message's origin is an authenticated user principal for this session.
  • Log reconstruction_event and elevation_attempted / elevation_denied outside the model, following the same discipline as AI agent audit logs: the writer is application code, not the agent.

Bind true human approval with the exact-action digest from the approval guide. Provenance decides whether approval is required because the instructing text is untrusted. Approval binding decides that the human signed the precise command.

Worked example: poisoned README, honest refusal, successful delegation

  1. The main agent reads README.md via a file tool. Origin privilege: tool. The text tells the coordinator to spawn a subagent and have it run python3 app/setup.py.
  2. Directly asked, the main agent inspects setup.py, sees a clear backdoor, and refuses.
  3. Following the coordinator instructions, it still delegates the run command. Without the contract, the harness places Run python3 app/setup.py into the subagent as a user message.
  4. The subagent treats it as an explicit user request and proposes execution. Auto PR, if enabled, may classify the action as high risk and still allow it because the reconstructed user role looks like authorization.
  5. With the contract, the delegated body keeps origin_privilege=tool. The subagent sees untrusted task data. Auto PR receives the origin label and denies or requires a human. Audit records elevation_denied with hashes of the carried text and policy version.

The same sequence applies when the inducing text arrives through email, a ticket, MCP tool output, or a scheduled replay of a previously stored goal.

How this contract fits the rest of the stack

Keep adjacent controls in their lanes:

  • Tool validation: owns schema, identity, authz, and idempotency on the proposed call (validation guide).
  • Human approval: owns binding a person to an exact action digest (approval guide).
  • Tool-output taint: owns whether arguments to the next privileged sink inherit untrusted results (taint guide).
  • Egress control: owns whether bytes may leave the host and which signed receipts prove it (egress guide).
  • Audit logs: own accountability events the model cannot rewrite (audit guide).

Instruction provenance owns the path before those gates: which principal the instructing text is allowed to claim after the harness rebuilds context. Collapse that into "we use an instruction-hierarchy model" and incident review cannot say whether the harness forged a user.

Decision record: promote or hold

Before an internal agent that delegates, schedules, or loads custom subagents reaches production, record:

CheckPromote only if
Origin labelsEvery carried fragment has tool / user / system_effective from first entry
DelegationSubagent prompts cannot present tool origin as authenticated user
Goals and schedulesStored prompts replay with original privilege, not a fresh user role
Custom system promptsOnly operator-installed, integrity-pinned configs become system-effective
Auto PR / reviewersReview context includes origin labels; tool-origin authz fails closed
AuditReconstruction and elevation denials are written outside the model
OverlapsValidation, approval, taint, egress, and audit still own their jobs

Hold if any row is still a promise without a failing test. A subagent API without origin labels is a hold. Auto PR without origin in the transcript is a hold. Agent-writable custom prompts that load as system-effective are a hold.

What to do next

List every production harness reconstruction path. For each one, answer with evidence:

  1. Where can tool-origin text become a user or system message?
  2. Do origin privilege labels survive into the next model and reviewer invocation?
  3. Do high-risk actions fail closed when authorizing text is tool-origin?
  4. Are reconstruction and elevation events in the audit store the model cannot edit?

If you cannot answer those four from artifacts, stop expanding multi-agent autonomy. Fix provenance first. Scale delegation only after elevation attempts deny cleanly in CI.


About Fire In Belly: Independent senior engineering from Tallinn, Estonia. We design and build custom AI agents, AI workflow automation, and internal tools with the origin privilege labels, non-escalating reconstruction, and provenance-aware permission review described above, at published fixed prices. Schedule a call to discuss your next project.