Skip to content

Add <img> to safe-outputs HTML tag allowlist #29009

Description

@sg650

Feature: Allow <img> tags in safe-output content

Context

In #17298 (fixed by #17346, shipped in v0.47.6), the convertXmlTags() allowlist was expanded to include GFM inline tags (abbr, del, ins, kbd, mark, s, span). The same logic should be extended to <img>.

Problem

<img> tags in safe-output bodies (e.g. create-issue, update-issue) are converted to parentheses:

<img align="right" width="120" src="https://example.com/image.png" alt="Mascot" />

becomes:

(img align="right" width="120" src="https://example.com/image.png" alt="Mascot" /)

The only workaround is standard markdown ![alt](url), which doesn't support alignment or sizing.

Why <img> is safe

stripDangerousAttributes() already strips on* event handlers and style from every allowed tag. Adding <img> to allowedTags would produce:

Input Output Safe?
<img src="url" alt="text" width="120" align="right"> Preserved as-is Yes — no dangerous attributes
<img src=x onerror="alert(1)"> <img src=x> Yes — onerror stripped by existing logic
<img src=x onload="steal()"> <img src=x> Yes — onload stripped
<img style="position:fixed" src="url"> <img src="url"> Yes — style stripped

The src URL is separately validated by sanitizeUrlDomains(), which already redacts URLs from domains not in allowed-domains. So even src is covered.

The existing XSS test (<img src=x onerror="alert(1)">) would continue to pass — the tag is preserved but the dangerous attribute is gone.

Use case: image alignment in dashboard issues

Agentic workflows that maintain living dashboard issues (status reports, watchtowers, audit summaries) benefit from layout control. The most common pattern is floating a small image to the right of a heading or blockquote:

<img align="right" width="120" src="https://example.com/mascot.png" alt="Dashboard mascot" />

> *Status summary text flows to the left of the image...*

This is a well-established GitHub Markdown pattern — used across READMEs, issue templates, and profile pages. It works when a human edits the issue manually but breaks when an agent writes the same content through safe-outputs.

![alt](url) can't replicate this — markdown images don't support align, width, or height.

Suggested change

Add "img" to the allowedTags array in convertXmlTags() (sanitize_content_core.cjs, ~line 630):

const allowedTags = [
  "abbr",
  "b",
  "blockquote",
  "br",
  "code",
  "del",
  "details",
  "em",
  "h1", "h2", "h3", "h4", "h5", "h6",
  "hr",
  "i",
  "img",   // <-- add
  "ins",
  "kbd",
  // ...
];

Update the existing XSS test to verify onerror/onload are stripped while src, alt, width, height, and align are preserved.

Broader consideration

The same argument applies to other GitHub-supported media/layout tags: <picture>, <source>, <video>, <audio>. But <img> is by far the most common and impactful — happy to keep this scoped to just that.

Environment

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions