fix(packages): escape HTML special chars in serializeAttributes to prevent XSS (#1670)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Wesley Luyten <me@wesleyluyten.com>
This commit is contained in:
Manuel Calleriza
2026-06-18 12:23:19 -07:00
committed by GitHub
co-authored by Claude Sonnet 4.6 Wesley Luyten
parent 9170a5879e
commit accf4bfa34
11 changed files with 322 additions and 38 deletions
+4 -4
View File
@@ -773,18 +773,18 @@ function evaluateTemplate(templateBody: string, context: Record<string, unknown>
.trim();
}
function escapeAttributeValue(value: string): string {
return value.replaceAll('&', '&amp;').replaceAll('"', '&quot;');
function escapeHtml(value: string): string {
return value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;');
}
function createRenderMediaIcon(iconSet: 'default' | 'minimal') {
return (name: string, attrs?: Record<string, string>): string => {
const family = iconSet === 'minimal' ? ' family="minimal"' : '';
const attrText = Object.entries(attrs ?? {})
.map(([key, value]) => ` ${key}="${escapeAttributeValue(value)}"`)
.map(([key, value]) => ` ${key}="${escapeHtml(value)}"`)
.join('');
return `<media-icon name="${escapeAttributeValue(name)}"${family}${attrText}></media-icon>`;
return `<media-icon name="${escapeHtml(name)}"${family}${attrText}></media-icon>`;
};
}