2.3 KiB
title, description
| title | description |
|---|---|
| T-S3: XSS payloads in frontmatter are HTML-escaped | The pre-Phase 1 build rendered XSS payloads in frontmatter title and description fields as live HTML in og:/twitter: meta tags and the page <title>. Post-fix every interpolation goes through attrEsc() or escHtml(). |
T-S3 — XSS payloads in frontmatter are HTML-escaped
This page exercises the T-S3 XSS via og:/twitter: meta tags
fix from battle-test-reports/test-report.md §S3 and
§T-S3. The frontmatter below contains classic XSS payloads.
Pre-Phase 1 they were rendered as live HTML in the generated
page. Post-fix they are HTML-escaped everywhere they appear.
The pattern
The frontmatter of this page contains:
---
title: '"><img src=x onerror=alert(1)> - Site'
description: '<script>alert("fm-xss")</script> Page description'
---
The rendered result (post-fix)
The <title> of the generated page contains the escaped version:
<title>"><img src=x onerror=alert(1)> - Site</title>
The og:title / twitter:title meta tags:
<meta property="og:title" content=""><img src=x onerror=alert(1)> - Site">
<meta name="twitter:title" content=""><img src=x onerror=alert(1)> - Site">
No live <script>alert(1)</script> in the page. No onerror
handler. The payloads are visible in the browser as literal
text — exactly what the user typed.
What the pre-fix output looked like
<title>"><img src=x onerror=alert(1)> - Site</title>
<meta property="og:title" content=""><img src=x onerror=alert(1)> - Site">
The XSS payload fired as soon as the page loaded. CI pipelines
that scanned for <script>alert( would have flagged it, but
the escaped version is what users see in their browser now.
How to verify
cd packages/_playground
node ../../packages/core/dist/bin/docmd.js build
grep -c "onerror" site/en/practical-tests/phase-3/xss-in-frontmatter/index.html
# 0
grep -c "<img src=x" site/en/practical-tests/phase-3/xss-in-frontmatter/index.html
# at least 1 (the escaped version)
The fix lives in:
packages/plugins/seo/src/index.ts(og:title, twitter:title)packages/plugins/pwa/src/index.ts(themeColor — separate fix)packages/plugins/analytics/src/index.ts(measurementId)packages/core/src/utils/exit.ts(generalised esc helpers from Phase 0 + Phase 3 PR 3.A)