# Unescaped HTML template interpolation

User or config values concatenated into HTML template strings or jQuery append without encoding

_Area: Web injection and code execution. Seen in 4 disclosed reports; 3 confirmed bounties, median $1,000, range $300-$3,000; latest 2026-09-04. Updated 2026-11-01._

## How it works
A value the attacker can influence is placed into an HTML template string, attribute, or DOM sink without encoding. The code assumes the value is plain text, but the browser parses it as markup, so any `<`, `>`, quote, or `</style>` in the value changes the document structure or starts a new element. The assumption that breaks is "this string is data"; the sink treats it as code.

## Where it shows up
- Template strings or concatenation building HTML, then fed to `innerHTML`, `dangerouslySetInnerHTML`, jQuery `$().append()`/`.html()`, or an HTML-accepting tooltip attribute [E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md)[E4](https://bugbountylibrary.com/r/h1%3A1588732.md)
- Library config built from user JSON and written into a `<style>` element [E1](https://bugbountylibrary.com/r/h1%3A1103258.md)
- Escaping helpers with a "already processed" flag stored in the same object as untrusted data [E2](https://bugbountylibrary.com/r/h1%3A246794.md)
- Attributes like `data-tooltip-html` that a component later renders as HTML [E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md)
- Values from issue summaries, titles, or config fields reaching these sinks [E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md)[E4](https://bugbountylibrary.com/r/h1%3A1588732.md)

## How to review
Trace each attacker-influenced value to its sink and confirm the exact invariant: **every value placed into an HTML context is encoded for that context, or the sink is a text-only API (textContent, React children, attribute set via property)**. Check:
- Is the sink HTML-parsing (`innerHTML`, `dangerouslySetInnerHTML`, jQuery append) rather than text? [E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md)[E4](https://bugbountylibrary.com/r/h1%3A1588732.md)
- Does any escaping helper let input opt out via a sentinel property? [E2](https://bugbountylibrary.com/r/h1%3A246794.md)
- Does a library merge user JSON into config that becomes CSS/HTML? [E1](https://bugbountylibrary.com/r/h1%3A1103258.md)
- Does CSP actually stop execution here, or does the sink still run script? [E4](https://bugbountylibrary.com/r/h1%3A1588732.md)

## How finders spotted it
- Read library source, saw directive JSON merged into config and concatenated into a `<style>` via innerHTML, then reasoned a `</style>` breakout was possible [E1](https://bugbountylibrary.com/r/h1%3A1103258.md)
- Code review of an escaping helper revealed a recursion-guard sentinel property, and realized attacker JSON could pre-set it [E2](https://bugbountylibrary.com/r/h1%3A246794.md)
- Noticed issue summaries flowed into `data-tooltip-html` and that the tooltip library rendered it via `dangerouslySetInnerHTML` [E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md)
- Code review found unescaped title interpolation in a template string, then traced rendering through jQuery append [E4](https://bugbountylibrary.com/r/h1%3A1588732.md)

## Variants seen
- CSS/`<style>` context breakout via fontFamily/themeCSS fields [E1](https://bugbountylibrary.com/r/h1%3A1103258.md)
- Escaping bypass through an attacker-settable sentinel property [E2](https://bugbountylibrary.com/r/h1%3A246794.md)
- Stored HTML injection through an HTML-accepting tooltip attribute [E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md)
- jQuery append executing `<script>` despite strict-dynamic CSP [E4](https://bugbountylibrary.com/r/h1%3A1588732.md)

## Impact and severity
Stored DOM XSS in GitLab issues [E1](https://bugbountylibrary.com/r/h1%3A1103258.md); DOM XSS on a Shopify widget domain [E2](https://bugbountylibrary.com/r/h1%3A246794.md); persistent iframe injection enabling phishing [E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md); XSS against project maintainers bypassing CSP [E4](https://bugbountylibrary.com/r/h1%3A1588732.md). Impact rises when the value is stored and shown to other users [E1](https://bugbountylibrary.com/r/h1%3A1103258.md)[E3](https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md), when it reaches privileged viewers like maintainers [E4](https://bugbountylibrary.com/r/h1%3A1588732.md), and when CSP is assumed to protect but does not [E4](https://bugbountylibrary.com/r/h1%3A1588732.md).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A1103258.md
- E2: https://bugbountylibrary.com/r/h1%3A246794.md
- E3: https://bugbountylibrary.com/r/bc%3A5c4b4697-bb0f-474f-b3e1-954d3758194e.md
- E4: https://bugbountylibrary.com/r/h1%3A1588732.md
