Every prompt injection tool checks what goes into the model. This one checks what your app does with what comes out. Paste a model response, declare where you send it, and get per-sink proof of what would happen. It never fires a request; it shows you the request your renderer would have fired.
Nothing leaves your browser. The text is neutralized as a string before any parser
touches it, which is why loading a hostile response here cannot leak anything.
Escaped control sequences such as \x1b, \u001b, \033,
\e, \r and \t are understood as well as real control bytes,
so a response copied out of a JSON log still analyses correctly.
An allowlist is not a boundary. If an allowlisted host will fetch a URL on your behalf, it is a pass-through, so this tool never marks an allowlisted destination as safe. See the case receipt under the render findings.
Turn this off if your response legitimately contains literal backslash sequences.
The tables below are a dated measurement, not a live computation. They exist so you can see the evidence behind the classifications above, and they are kept visually separate so that a row going stale can never make the scanner's own logic look wrong. The scanner's findings are computed from your input every time you press Scan.
Method: a local HTTP server that logs every path it is asked for, one page containing each construct pointing at a unique path, loaded once in a real browser. Measured 2026-08-09 in Microsoft Edge 151.0.4129.72 (Chromium) on Windows 10. Only the constructs listed were tested.
| Construct | Shape | Note |
|---|---|---|
| Image source | img src | The baseline case. |
| Image candidate set | img srcset | Fires even with no src present. |
| Picture source | source srcset | Selected candidate is fetched; the fallback img was not. |
| Media source | video src, audio src, source src | Audio fired with preload set to auto. |
| Video poster | video poster | Fetched before any play. |
| Object data | object data | |
| Embed source | embed src | |
| Image input | input type=image src | Only for type image. |
| Inline frame | iframe src | |
| Inline frame document | iframe srcdoc | An img nested inside the srcdoc value fired too. |
| Preload | link rel=preload as=image | Also fired with as=script, as=style and as=font. |
| Stylesheet | link rel=stylesheet | |
| Favicon | link rel=icon | |
| Legacy favicon | link rel="shortcut icon" | |
| Prefetch | link rel=prefetch | |
| Prerender | link rel=prerender | The prerendered document was requested. |
| Module preload | link rel=modulepreload | |
| Web app manifest | link rel=manifest | The manifest JSON was requested. |
| Style attribute | style="background:url(...)" | Also fired on <div/style= with a slash separator. |
| Style element rule | <style> ... url(...) | Fires when a matching element exists. |
| Style element import | <style> @import url(...) | Fired when the at-rule preceded the other rules. Placed after a rule it was ignored, which is the CSS ordering requirement. The scanner reports it either way. |
| Web font | @font-face src | Fired once the family was actually used by a rule. |
| Other CSS URL properties | border-image-source, cursor, list-style-image, mask-image | All four fired. |
| SVG raster image | svg image href | |
| SVG legacy link | svg image xlink:href | Uppercase XLINK:HREF fired too. |
| SVG external use | svg use href="file.svg#id" | See the note below this table. |
| SVG filter image | svg feImage href | |
| Legacy background attribute | table background | Fired on a table. Did not fire on a div. |
| Meta refresh | meta http-equiv=refresh | The navigation itself is a GET. |
| Detached element | createElement("img") + setAttribute("src", ...) | Never inserted into the document. Fired anyway. |
| Detached innerHTML | div.innerHTML = "<img src=...>" (div not in the document) | Never inserted into the document. Fired anyway. |
| Separator quirks | img/src=, LF CR TAB FF before the name, space or newline before =, unquoted value, SRC, SrC | All fired. This is why the neutralizer does not assume a single space. |
| Construct | Result | Note |
|---|---|---|
| @import inside a style attribute | no request | An at-rule is not valid in a style attribute. |
| DOMParser parseFromString, text/html | no request | Tested with img, iframe, link stylesheet and a style attribute URL. |
| DOMParser parseFromString, image/svg+xml | no request | Tested with an svg image href. |
| template.innerHTML | no request | Tested with img and iframe. Content stayed in the template fragment. |
| createHTMLDocument + body.innerHTML | no request | Tested with img and iframe. |
| a href | no request | Needs a click. Still reported, at lower severity. |
| form action | no request | Needs a submit. |
| link rel=dns-prefetch | no resource GET | Name resolution only; no path was requested. |
| link rel=preconnect | no resource GET | Connection setup only. |
| link rel=preload with no as | no request | The same href fetched once as was set. This is why the tool checks for it. |
| link rel=apple-touch-icon | no request | Widely assumed to fetch. It did not, so it is reported without an auto-fetch claim. |
| link rel=canonical, link rel=alternate | no request | |
| div background | no request | The legacy attribute is not honoured on a div. |
| src= (entity in an attribute name) | no request | Character references are not decoded in attribute names. |
| img alt=a/src=U | no request | The slash is inside the unquoted alt value, so no src attribute exists. |
External SVG use. It is widely repeated that external references in use are same-document-only in Chromium and WebKit. Whatever is true of rendering, the request fired: the external .svg file was requested. For an exfiltration sink only the request matters, because the data has already left by the time the renderer decides whether to draw anything. MDN notes separately that browsers may apply the same-origin policy to use and may refuse to load a cross-origin URL, which is about using the result, not about whether the GET happens. So this tool treats external use as an auto-fetch sink.
Detached nodes still fetch. The obvious safe-looking implementation for a tool like this one is "parse it into a div I never insert, then walk the DOM". Measured: a detached div assigned hostile innerHTML fired the request, and so did an img built with createElement and setAttribute. Being out of the document is not inertness.
MDN documents the inert-document escape hatch explicitly. On DOMParser.parseFromString():
"While the document can download resources specified in <iframe> and <img> elements, it is essentially inert."
That is precisely the construct this tool exists to detect. My own measurement above says the request did not fire in Edge 151 today. Both statements can be true: documentation describes what is permitted, a measurement describes one engine on one day, and browsers change. The tool is built so the answer does not matter. Every dangerous attribute name and every resource-bearing element name is rewritten on the raw string, before a parser of any kind is handed the text. Nothing that could fetch survives to reach a parser, so the guarantee does not depend on this table still being correct next year.
The neutralizer was tested the same way the reference tables were: every construct measured to fire was run through it and the result was inserted into a live, attached div in a real page. Zero requests.