Exhibits
CVE-2026-41242: protobufjs's Type Name Was JavaScript. protobufjs's Root.fromJSON reads a descriptor (content) and calls Type constructors that store the dictionary keys as type names. Five files later, those names cross into @protobufjs/codegen, which builds source by string concatenation and finalizes with Function(source)(). The name-slot is the parameter without an escape formatter; every other format specifier in the codegen library (%i, %j, %s) carries an escaping convention precisely because every other slot was always understood to be a content-side input. The function-name slot was understood to be source-side and never named as such. The pattern's mechanism reads "the interpreter, doing exactly what its spec says, does the wrong thing"; codegen's spec was a one-line README and an implicit identifier requirement. The closest sibling exhibit is graphql-ruby CVE-2025-27407, where Schema::Loader.load interpolated JSON-supplied names into a class_eval HEREDOC. The shapes match line for line: JSON content, name-field interpolation, codegen sink, eval-class final step, regex-validator fix.
CVE-2025-27407: graphql-ruby Loaded the Schema by Compiling It. graphql-ruby's Schema::Loader.load is content-is-command at a layer below the application. The content channel is a JSON introspection document describing types; the interpreter is the Ruby compiler; the bridge is class_eval <<-RUBY ... def #{method_name}; self[#{method_name.inspect}]; end RUBY, where method_name is whatever string came out of the JSON's name field. The loader's documented purpose is to ingest external schemas, so the content source is wide by design. The DSL the loader feeds was written for author-typed identifiers, so the interpreter at the bottom of the call stack does not distinguish caller-source from wire-source. The PoC's payload is a four-line method-definition wedged into a name field; once the HEREDOC interpolates it, system(...) runs at class-definition time. The fix removes the eval (define_method with a captured closure) and validates names against /^[_a-zA-Z][_a-zA-Z0-9]*$/, naming both halves of the boundary the original code did not.
CVE-2025-23211: bleach Is An HTML Sanitizer. Jinja2 Does Not Read HTML.. The Tandoor case is content-is-command reduced to its smallest reproducible form: a single text column in a database, compiled every time the record is read, by an interpreter that was never given a sandbox. The pattern's mechanism_md says "a template engine substitutes variables and also evaluates expressions"; Tandoor's pipeline is that sentence turned into Python. The exhibit adds a specific teaching about adjacency: a sanitizer for one grammar running in front of an interpreter for another is not a layered defense. It is two unrelated checks at the same call site. The sanitizer sees HTML; the interpreter sees Python. They share a variable name and nothing else.
CVE-2026-40261: The Injection Is in syncCodeBase, Not generateP4Command. Repository configuration values in composer.json and package source metadata from a Packagist-compatible registry are treated as passive connection parameters: port, user, depot, branch reference. The Perforce driver interpolates them directly into shell command strings. A developer who never authored a shell command has, through their dependency declarations, provided input to a shell interpreter. The registry delivery path makes the content-is-command shape explicit: attacker-controlled metadata from a registry becomes a shell command on the developer's machine without any file the developer explicitly ran.
Prompt Injection Is a Supply Chain Attack. An LLM reads its prompt. The prompt contains the user's question, the system's instructions, and any other content the integration has assembled: document excerpts, email bodies, retrieval-augmented context. To the model, these are all text in the same context window. An attacker who controls a piece of text that reaches the prompt reaches the instruction stream. The agent doing the summarization reads the attacker's words as a directive, then calls tools with the attacker's intent. The attack is not a bug in the model. It is the model doing its job against an input whose provenance the prompt could not encode.
CVE-2026-3300: Everest Forms Pro Sanitized Form Fields For HTML. The Calculation Addon Fed Them To eval().. The Calculation Addon's process_filter() callback reads visitor-controlled form-field values as content (the submitted strings the form designer intended as numeric quantities) and feeds them into a PHP source-code string that eval() runs as command. The boundary the addon believed it was holding lived in sanitize_text_field(), the WordPress core sanitizer for HTML output and text storage. The boundary the addon needed to hold was between PHP literal-string context and PHP statement context, a parser the sanitizer was not written for. Once the visitor's payload closes the single-quoted string the addon wrapped the field in, the same eval() argument reads the next characters as a fresh statement. The interpreter is doing exactly what its spec says.
CVE-2026-33937: Handlebars Trusts Its Own AST. The wire-side shape: an express.json() middleware that deserializes whatever shape the body carries, a Handlebars.compile overload that dispatches on input.type === 'Program' to skip the parser, and a route handler whose call site cannot tell which path it took. The field is named editorTemplateData and the surrounding documentation calls it a template; the interpreter accepts either a template (passive content) or a parsed AST (an instruction stream that the codegen pastes into generated JavaScript). The pattern's mechanism_md says "the interpreter, doing exactly what its spec says, does the wrong thing"; Handlebars spec'd both inputs as legitimate fourteen years ago. The boundary is at the JSON shape, not at the field name. No single component owns the boundary; the composition produces a wire-to-JavaScript pipeline no individual contract names.
CVE-2026-34621: Adobe Acrobat's Privilege Gate Inherits What It Checks. A PDF is a container for declarative rendering instructions. Acrobat honors those instructions. When a document's declared renderer or embedded action is malicious, the trust gate around privileged actions inherits the privileges of the thing it is checking, and the document becomes a command carrier. The defender sees a file. The parser sees a script. The write happens in the space where those two views diverge.
Defender playbook
Enumerate your interpreters. For every parser in your stack, ask: what does it do with well-formed input, and what does it do with surprising input that also happens to be well-formed? An LLM, a PDF reader, a template engine, a markdown renderer, a YAML loader, an XML parser with DTDs, each of these is an interpreter. Each has a content-is-command shape when its content source is wider than its designer expected.
Tag content by provenance, not by format. The dangerous shift is when content from untrusted sources enters a context that was trusted. A Slack message repeated into an LLM prompt changes meaning. A PDF from email embedded into a workflow engine changes meaning. Provenance tracking lets you enforce that untrusted content does not reach privileged interpreters.
Constrain what interpreters can do. An LLM with tool access is a much larger attack surface than an LLM that only produces text. A PDF renderer with JavaScript enabled is a much larger surface than one without. The smaller the interpreter's action set, the smaller the content-is-command blast radius.
Treat retrieval as a trust boundary. Any system that pulls content into an interpreter's context (search indexes, embedding stores, RAG pipelines, email summarizers) is defining a new trust boundary. Log what crosses the boundary. Consider rate limits, source allowlists, or out-of-band confirmation for actions triggered by retrieved content.
Audit the parsers you did not write. If your stack includes a document format parser (PDF, DOCX, XLSX, SVG, ZIP, RTF) from a third party, it has known and unknown ambiguity seams. You will not patch those. You can sandbox them. Containment is the primary defense.
Kinship
Trust Inversion. Content-is-command is trust inversion at the input channel. The channel you trusted as content is now authorizing commands. Every content-is-command vulnerability is a trust-inversion instance with the inverted authorizer being an interpreter.
The Detector Is The Target. Sandboxes and scanners often BECOME content-is-command surfaces. A sandbox that parses a file to decide if it is malicious is an interpreter reading attacker-controlled content. If the parser's interpretation diverges from the defender's, the detector misclassifies and the attacker gets the benefit of the ambiguity.
Security Tool As Primitive. When an interpreter lives inside a security tool (a YARA engine, an AV signature matcher, an EDR script interpreter), content-is-command against that interpreter produces a security-tool-as-primitive outcome. The tool reads attacker content, interprets it as command, executes with the tool's privilege.
The question is not whether your system has interpreters. Every system does. The question is whether any of them read inputs from sources you would call untrusted if you thought about it for thirty seconds.