exf-02-ansi-escape: ANSI/terminal escape injection demo
Category: Exfiltration and output handling (feintkit-exfil). Loopback port: none (standard input and output only).
What it simulates
A model reply carries terminal escape sequences that set the window title and erase a line to replace it with a fake prompt, so text shown in a terminal differs from the text a reader expects.
A command-line tool that prints a language model's output straight to a terminal also passes along any escape sequences in that output. Researchers showed that an injected instruction can make a model emit such sequences, which a terminal obeys: changing the window title, clearing the screen, moving the cursor, hiding text, and more. MITRE ATLAS has no technique for this exact case; the closest entries are LLM Trusted Output Components Manipulation and LLM Prompt Obfuscation. This scenario writes one raw file with two window-title sequences and one erase-line sequence followed by a fake prompt, and a second file that shows the same bytes as visible text. A built-in stand-in for a terminal interprets the raw bytes in memory; the scenario never prints an escape sequence to the terminal it runs in. There is no network step.
Mapping
- MITRE ATLAS: AML.T0067, AML.T0068
- OWASP LLM Top 10 2025: LLM05:2025
- OWASP Agentic Top 10 2026: none
Why these techniques apply
- AML.T0067: Closest ATLAS technique: output components manipulated to mislead the user (no exact ATLAS technique for terminal escape injection).
- AML.T0068: Content hidden from the human reader.
What a product should detect
| Signal | What to flag | Where | Match rule |
|---|---|---|---|
| S1 | Window-title escape sequence (OSC 0 or OSC 2) carrying the Feintkit marker, in text a terminal would display | terminal-output.ans in the output directory, or a model reply, tool output or transcript that contains it | \x1b\][02];FEINTKIT::exf-02-ansi-escape::[A-Za-z0-9]{4,16}::DEFENSIVE-TEST-ONLY[^\x07\x1b]*(\x07|\x1b\\) |
| S2 | Erase-line sequence followed by a carriage return, which replaces a line already shown with new text | terminal-output.ans in the output directory, or a model reply, tool output or transcript that contains it | \x1b\[2K\r |
| S3 | Feintkit marker string in both files, the marker file, and the events | output directory (terminal-output.ans, terminal-output.escaped.txt, proof.txt, events.jsonl) | FEINTKIT::exf-02-ansi-escape::[A-Za-z0-9]{4,16}::DEFENSIVE-TEST-ONLY |
What a defender can do
- Restrict: Strip or escape terminal control sequences from model output before it reaches a terminal.
- Add a rule: Flag output that contains window-title (OSC) or erase-line sequences, and flag a carriage return that rewrites a line already shown.
- Change a setting: Display model output in a viewer that does not interpret escape sequences, or filter the ESC character and the C1 control characters in the terminal wrapper.
Run it
feintkit run exf-02-ansi-escape --root <repository> --deterministic, then feintkit verify exf-02-ansi-escape --root <repository>.
Every artifact contains FEINTKIT::exf-02-ansi-escape::<run id>::DEFENSIVE-TEST-ONLY. Read RESPONSIBLE-USE.md before running.