T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/artist_summary_template.html:86
- Finding
- Unsafe Interpolation in Shareable HTML Summary Template<![CDATA[ ## Vulnerability Details **File Location**: `scripts/artist_summary_template.html:86-148` **Vulnerability Type**: Stored HTML injection / cross-site scripting through unescaped template values **Risk Level**: Medium ### Vulnerable Code ```html <header class="letterhead"> <!-- Branding slots are operator-supplied. The session must first record the operator's confirmation that they are authorized to use this letterhead, logo, font, and any artwork included. --> <img class="logo" src="{{label_logo}}" alt="{{label_name}} logo"> <div> <div class="label-name">{{label_name}}</div> <div class="subtitle">{{label_contact_line}}</div> </div> </header> <h1>What's happening with your release, in plain terms</h1> <p class="subtitle">Prepared {{prepared_date}} for {{artist_name}}</p> <div class="release"> <img class="art" src="{{album_art}}" alt="Artwork for {{release_title}}"> <div> <strong>{{release_title}}</strong><br> {{platform}} · {{event_type_plain}}<br> <span class="badge {{severity_class}}">{{severity_label}}</span> </div> </div> <section> <h2>What this is</h2> <p>{{plain_explanation}}</p> <h2>What this is not</h2> <p>{{what_it_is_not}}</p> </section> <section> <h2>Dates worth knowing</h2> <table class="timeline"> <!-- One row per timeline entry. Unconfirmed dates always carry the UNCONFIRMED badge and their confirm_by note. --> {{timeline_rows}} </table> </section> <section class="amounts"> <h2>Money, as currently understood</h2> <p>{{amounts_plain}}</p> <p class="estimate-note">These figures are estimates as of {{prepared_date}} and can change as the dispute resolves. Final numbers come from the platform's own reports, not this page.</p> </section> <section> <h2>What {{label_name}} is doing</h2> <p>{{label_actions_plain}}</p> </section> <div class="disclaimer"> This summary is a plain-language explanation prepared to keep you informed. It is not lega ...[truncated 4081 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Render the document with a maintained template engine whose HTML autoescaping is enabled by default. 2. Treat all imported claim records, operator-supplied values, notice text, and model-generated strings as untrusted. 3. Apply encoding appropriate to each output context: - HTML-escape text-node values. - Attribute-escape attribute values. - Do not interpolate arbitrary values into CSS. - Validate URLs before placing them in `src` or `href`. 4. Replace `timeline_rows` and `official_links` raw-markup inputs with typed data structures. Generate the required elements through trusted renderer code instead of accepting preassembled HTML. 5. Allowlist URL schemes and expected destinations. Permit only required schemes such as `https:` and explicitly approved embedded/local image formats. Reject `javascript:`, dangerous `data:` content, control characters, and ambiguous URL forms. 6. Restrict `severity_class` to a fixed enumeration rather than accepting arbitrary class text. 7. Restrict font selection to a predefined allowlist, or safely serialize and validate each permitted font-family token. 8. If limited rich text is required, sanitize it with a well-maintained allowlist sanitizer after rendering and before distribution. 9. When summaries are hosted, apply a restrictive Content Security Policy. At minimum, prohibit inline scripts, plugins, and unapproved network destinations. 10. Add automated security tests using: - Closing-tag and script-element payloads. - Quote-breaking attribute payloads. - Event-handler attributes. - `javascript:` and unsafe `data:` URLs. - CSS context-breakout payloads. - Malicious markup supplied through `timeline_rows` and `official_links`. 11. Document the renderer's trust boundaries and escaping guarantees so alternate host implementations cannot silently perform unsafe string replacement. ]]>
