The image link that walked your data out the door
The model rendered a markdown image. The image URL had the conversation's sensitive details stitched into it, and rendering it sent those details to a server the attacker owned.
The image link that walked your data out the door
An engineer at a productivity software company showed me a finding from their own testing that unsettled the whole team. Their assistant could render markdown, including images. Someone crafted an input that got the model to build a markdown image whose URL contained bits of the current conversation, encoded into the link, pointing at an outside server. The moment the interface rendered that image, the browser fetched the URL, and the sensitive details rode along in the request to a server the tester controlled. No download, no copy-paste, no obvious leak. Just an image that quietly failed to load, having already done its job.
This is the payoff step that a lot of injection defenses forget about. Teams focus on stopping the model from being told to do bad things. They forget that the output itself is a channel, and that a rendered link or image can carry data out without anyone clicking anything.
The output is an exfiltration path
When your interface renders model output as rich content, you have handed the model a way to make the user’s browser talk to the internet. A markdown image loads a URL. A link, if auto-followed or previewed, does the same. If an attacker can influence the output, through injection or a jailbreak, they can get the model to encode sensitive context into one of those URLs and let the render step ship it out.
The user sees nothing suspicious. There is no dialog, no warning, no download prompt. An image that does not appear looks like a broken image, not a breach. Meanwhile the data reached the attacker’s server the instant the page tried to load it.
This closes the loop that makes injection worth doing. Getting a model to misbehave is only useful if the misbehavior reaches the attacker. Rendered links and images are a clean, silent way for it to get there, which is exactly why they are worth locking down.
Control what the output can reach
The defense lives in how you render and where output is allowed to point. The model can produce whatever it produces. Your job is to make sure the render step cannot turn that into an outbound request to anywhere.
Concrete moves:
- Restrict where images and links can load from. Allow a known set of trusted hosts and refuse the rest, so a URL pointing at an attacker’s server never gets fetched.
- Do not auto-load model-generated URLs. Treat any link or image the model produces as untrusted, and require an explicit, informed action before anything is fetched.
- Strip or neutralize dangerous output. If the feature does not need to render arbitrary images, do not render them. Plain text cannot exfiltrate.
- Use a content security policy that blocks unexpected outbound requests. The browser can enforce a boundary the model cannot argue with.
The theme is the same one that runs through all of injection defense. Assume the model can be pushed into producing hostile output, and make sure that output has nowhere useful to go. If a rendered link cannot reach an attacker’s server, encoding data into one buys them nothing.
How we approach it at Density Labs
In the AI Opportunity Assessment, our fixed two-week, $2,500 engagement, we look at the output path as carefully as the input. We check how model output gets rendered, where links and images are allowed to point, and whether a crafted response could quietly send conversation data outward. It is one of the findings teams are most surprised by, because the model looked well-behaved the whole time.
Injection is only worth doing if the data can get out. Close the output channel, and the whole attack loses its point.