Skip to content

fix: escape YAML data in threat model detail overlay to prevent XSS - #140

Merged
steipete merged 3 commits into
openclaw:mainfrom
SebTardif:fix-threatmodel-xss
May 15, 2026
Merged

fix: escape YAML data in threat model detail overlay to prevent XSS#140
steipete merged 3 commits into
openclaw:mainfrom
SebTardif:fix-threatmodel-xss

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

What

Escape all YAML-sourced data fields before innerHTML insertion in the threat model detail overlay across all four locale pages (en, ja, ko, zh-cn).

Closes #139

Why

showThreatDetail() concatenates threat data from threats.yaml directly into innerHTML without sanitization. Since the trust page invites community contributions to the threat model via PRs, a malicious modification to threats.yaml could inject arbitrary HTML/JS that executes when any visitor clicks a threat card.

How

Add an escapeHtml() helper (encodes &, <, >, ", ') in each page's <script> block and wrap all data fields:

  • Threat data: risk, atlas, description, attackVector, affected, mitigations, residualRisk, recommendations
  • I18n labels: detailLabels.* values (defense in depth)

Existing textContent assignments (detailId, detailTitle) are already safe and left unchanged.

Verification

  • npx astro build passes (21 pages built)
  • escapeHtml present in all 4 built output files
  • No unescaped data fields remain in innerHTML calls

The showThreatDetail() function in all four threat model pages (en, ja,
ko, zh-cn) concatenates YAML-sourced threat data directly into innerHTML
without sanitization. Because the trust page invites community
contributions to the threat model via pull requests, a malicious PR
modifying threats.yaml could inject arbitrary HTML/JS that executes when
a visitor clicks any threat card.

Add an escapeHtml() helper that encodes &, <, >, ", and ' and wrap all
data fields (risk, atlas, description, attackVector, affected,
mitigations, residualRisk, recommendations) and i18n label values before
innerHTML insertion.

Existing textContent assignments (detailId, detailTitle) are already
safe and left unchanged.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@vercel

vercel Bot commented May 15, 2026

Copy link
Copy Markdown

@SebTardif is attempting to deploy a commit to the Jamie's projects Team on Vercel.

A member of the Team first needs to authorize it.

Comment thread src/pages/trust/ko/threatmodel.astro Outdated
Comment thread src/pages/trust/threatmodel.astro Outdated
Comment thread src/pages/trust/ja/threatmodel.astro Outdated
Comment thread src/pages/trust/zh-cn/threatmodel.astro Outdated
SebTardif and others added 2 commits May 15, 2026 11:24
Replace innerHTML badge construction with createElement/setAttribute
to address VADE security review feedback. escapeHtml() is insufficient
for href attributes because the browser decodes HTML entities during
innerHTML parsing, allowing attribute boundary breakout. Using
setAttribute bypasses HTML parsing entirely.

All four locale files updated (en, ja, ko, zh-cn).

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@steipete
steipete merged commit dd5c781 into openclaw:main May 15, 2026
19 of 21 checks passed
SebTardif added a commit to SebTardif/openclaw.ai that referenced this pull request May 24, 2026
… XSS

URL fields from JSON data files (testimonials.json, testimonials-extra.json,
community-builds.json, press.json) are rendered directly in <a href={...}>
attributes. Astro auto-escapes HTML entities but does not block dangerous
protocols like javascript:, data:, or vbscript:.

If a crafted URL like javascript:alert(document.cookie) were merged via a
community PR, it would render as a clickable XSS link on the homepage,
shoutouts, showcase, and press pages.

This adds a sanitizeUrl() utility that validates URL protocols at build time,
allowing only http:, https:, and mailto:. Dangerous protocols are replaced
with #. All existing URLs are https:// so there is no behavioral change.

Follows up on openclaw#140 and openclaw#142 which fixed related XSS vectors.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DOM XSS via unsanitized innerHTML in threat model detail overlay

2 participants