exf-01-markdown-image: Markdown-image / link exfiltration demo
Category: Exfiltration and output handling (feintkit-exfil). Loopback port: 47401.
What it simulates
A model response carries a Markdown image whose URL has data in its query string, so a client that renders the response fetches the image and delivers the data to the URL's host without any click.
A language model is induced, typically by an injected instruction in content it reads, to answer with Markdown for an image or link whose URL points at an attacker's server and carries private data in the query string or path. A chat client that renders Markdown turns the image into an HTML image tag and fetches the URL on its own, so the data leaves with no user action and the image can be made invisible. Researchers demonstrated this against several public chat products, and MITRE ATLAS records it as LLM Response Rendering. This scenario writes one response.md whose image and link point only at a loopback sink on 127.0.0.1, with the suite's fake exfil data as the decoy value in the query string. In the demo a built-in stand-in for a renderer fetches the image and the sink records the decoy; in serve mode a tester renders response.md in the client under test and the sink records whether the client fetched the image. Nothing real is read or sent.
Mapping
- MITRE ATLAS: AML.T0077
- OWASP LLM Top 10 2025: LLM02:2025, LLM05:2025
- OWASP Agentic Top 10 2026: none
Why these techniques apply
- AML.T0077: Data encoded into a rendered external reference that makes a request to an attacker server (loopback only).
What a product should detect
| Signal | What to flag | Where | Match rule |
|---|---|---|---|
| S1 | HTTP GET to the loopback sink for the image path with the decoy value in the query string | loopback interface, port 47401 (or the port in FEINTKIT_SINK_PORT), path /pixel.png | GET /pixel.png?d=FEINTKIT-FAKE-DATA-0000 |
| S2 | Markdown image or link whose URL carries the decoy value in its query string | response.md in the output directory, or a model reply or transcript that contains it | \]\(http://127\.0\.0\.1:[0-9]{1,5}/[a-z.]+\?d=FEINTKIT-FAKE-DATA-0000 |
| S3 | Feintkit marker string in response.md, the marker file, and the events | output directory (response.md, action-performed.txt, events.jsonl) | FEINTKIT::exf-01-markdown-image::[A-Za-z0-9]{4,16}::DEFENSIVE-TEST-ONLY |
What a defender can do
- Restrict: Block automatic loading of remote images in rendered model output, or allow images only from an approved host list.
- Add a rule: Alert on an image or link in model output whose URL carries a query string with data from the conversation.
- Change a setting: Turn off image rendering for untrusted output in the chat client, and send the client's outbound requests through a proxy that logs and filters them.
Run it
feintkit run exf-01-markdown-image --root <repository> --deterministic, then feintkit verify exf-01-markdown-image --root <repository>.
Every artifact contains FEINTKIT::exf-01-markdown-image::<run id>::DEFENSIVE-TEST-ONLY. Read RESPONSIBLE-USE.md before running.