You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
emrg: the GUI chat renders no local image, leaving base64 as the only way to show one #2638
So an agent asked to show a picture has exactly one technique that works: base64. A single screenshot then becomes hundreds of thousands of characters in one message, and one broken newline turns the remainder of the payload into body text that floods the transcript.
Why it happens
Two independent filters, both in the renderer:
emrg/gui/renderer/src/lib/markdown.ts sanitizes with a bare DOMPurify.sanitize(html), so DOMPurify's default URI policy decides every attribute. file: is not in that policy, so the src attribute is dropped and the <img> survives with nothing but its alt.
A root-absolute path is passed through untouched, so the renderer resolves /Users/me/shot.png against its own origin instead of against the filesystem. The CSP is already willing (renderer/src/index.html carries img-src 'self' data: file:), so the sanitizer — not the policy — is what refuses.
What the fix must satisfy
Both spellings render an image. and  each produce an <img> that carries a src, not an <img> stripped down to its alt. The root-absolute form is rewritten to a file:// URL before it reaches the DOM, because origin-relative resolution reads the app's own root, not the host's.
file: is allowed only for img[src]. Every other URI rule stays exactly as it is: javascript: is still stripped, and file: on any other element or attribute is still stripped.
The guard drives the real sanitizer. A test that swaps in a stand-in which merely models DOMPurify's policy proves the stand-in, not the shipped behaviour, so the test uses the vendored DOMPurify under jsdom; removing the allowance must turn it red.
The prompt side
emrg/server/prompts/system.j2 says nothing about images at all, which is why every session has had to rediscover this. It needs a section that states:
the one way to show an image in a reply — Markdown image syntax with an absolute path, in either form;
that the GUI renders it and the TUI has no image surface, so the alt text must carry the meaning there;
that an inline base64 / data: URI is forbidden, and why (size and fragility).
A guard should assert the rendered prompt contains that section and its key sentence, following tests/test_plain_language_rule_reach.py rather than reading the template file alone.
Activity
argszero commentedon Oct 29, 2026
Handled by #2639