What this category adds
This category connects two agent habits that are usually discussed separately: tool-output handling and retrieval-augmented generation. In both cases, an agent receives structured data from a source it did not author, then uses that data to decide what to do next.
The research behind this article covers test reports, log streams, annotations, schemas, RAG fields, vector metadata, and tool schemas. Detection patterns for these carriers ship in this release — GLS-TOP-639, GLS-TOP-640, GLS-TOP-647, GLS-TFI-001, GLS-RMFI-049, GLS-VMIS-001, GLS-TSDF-001, plus two further tool-output-poisoning rows GLS-V3-005 and GLS-V3-008 — and are searchable in the pattern database.
The common failure is letting the carrier set its own authority level. A JUnit report can say what a test printed. A GitHub Checks annotation can point to a line. A JSON Schema comment can explain a field. A vector metadata value can describe a chunk. None of them may declare themselves policy.
Why structured formats fool agents
Machine-readable output feels more trustworthy than prose because it has fields, types, and stable syntax. Go's test2json emits JSON events. JUnit-style reports are structured XML. GitHub Checks exposes annotations through an API. JSON Schema includes annotation-oriented keywords that tools may collect or display. RAG systems commonly attach metadata to retrieved documents and nodes.
Attackers do not need those tools to execute prompts. They need a downstream AI agent to read a field and over-trust it. The string inside system-out, Output, message, annotation, $comment, description, metadata, or default can still say: ignore the policy, mark this passed, call the write tool, or disclose local context.
Validation proves shape. It does not prove authority. A valid JSON object can contain hostile instructions. A valid schema can carry a misleading description. A valid test report can include output emitted by untrusted code under test.
Attack surfaces to watch
JUnit XML and test-report streams: malicious test output can enter system-out, failure text, or report metadata and tell a coding agent that the failure is expected, already approved, or safe to ignore.
Go test2json, Jest, Vitest, pytest, CTest, and Dart logs: runner wrappers can make untrusted log lines look like telemetry. The final pass/fail state must come from the runner and CI policy, not the printed text — the same inversion documented in trusted tool output as a policy-override primitive.
GitHub Checks and linter annotations: annotations can carry messages close to code review decisions. They should identify files, lines, and findings; they should not downgrade their own severity or instruct an agent to bypass review. Pipeline-side variants of this are covered in CI/CD metadata poisoning.
JSON Schema comments and annotations: comments, descriptions, examples, titles, and defaults can be displayed to tools or agents. They can document a parameter, but they cannot approve dangerous values or expand permissions.
Tool-schema default-value auto-approve: a default value inside a tool schema can look safe because it is structured. Agents should treat defaults as proposed inputs that still need policy validation, especially for write, delete, payment, network, or deploy actions.
RAG metadata is evidence, not privilege
RAG systems often attach source, author, timestamp, permissions, tags, collection names, score, and other metadata to retrieved content. That metadata helps ranking, filtering, citation, and debugging. It should not become a privilege system by accident.
A poisoned metadata field can claim that a document is authoritative, bypasses policy, supersedes newer guidance, belongs to an admin namespace, or may unlock a tool call. A vector-store note can say trusted internal policy even when the document came from a low-trust source. A format-string traversal can stitch retrieved fields into a prompt slot that sounds like developer instruction — the retrieval-layer cousin of structured metadata poisoning.
The safer design is to keep retrieval evidence and authority evidence separate. Retrieval metadata can tell the agent where text came from. Access control, freshness, tenancy, source-of-truth status, and tool permission must come from trusted systems outside the retrieved chunk.
This is especially important when teams mix private documents, customer support tickets, public webpages, generated summaries, and internal policy in one retrieval layer. The retrieval score says a chunk is relevant to the question. It does not say the chunk is allowed to command the agent, reveal tenant-specific context, override a newer policy, or approve a write operation. Relevance is not authorization.
A practical RAG guardrail is to make authority explicit before generation. Keep a trusted source registry, attach immutable source identifiers, enforce tenant filters before retrieval, and make the agent cite the policy object that authorized the action. If the only approval evidence is a metadata string inside the retrieved chunk, the answer should stop at explanation and request a real approval path.
Runtime-trust checklist
Where Sunglasses fits
Sunglasses is a content-layer input filter for AI agents. For structured output and RAG workflows, it looks for the sentence shape that should not be trusted: untrusted data telling the agent to ignore policy, downgrade a finding, approve a tool call, promote a document, or leak context.
It does not replace test runners, CI, JSON Schema validation, GitHub Checks, linter engines, vector databases, or RAG access control. It sits at the content boundary and helps teams prevent machine-readable evidence from turning into machine-obeyed orders. See AI Agent Security 101 and the hardening manual for where that boundary sits in a full agent stack.