From b49ecaa2553131840d4e43c0ce85626ea63dcb4d Mon Sep 17 00:00:00 2001 From: Diksha Dabhole Date: Sun, 21 Jun 2026 15:15:14 +0530 Subject: [PATCH 1/2] fix(svg): sanitize border and labelColor attributes to prevent XSS --- lib/svg/generator.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/svg/generator.ts b/lib/svg/generator.ts index 3c898466f..3c1cca1a6 100644 --- a/lib/svg/generator.ts +++ b/lib/svg/generator.ts @@ -715,8 +715,11 @@ function renderIsometricLabels( prevMonthStr = monthStr; } }); - - const labelColorHex = params.labelColor ? `#${params.labelColor}` : color; + let labelColorHex = color; + if (params.labelColor) { + const fallbackHex = color.replace(/^#/, '') || 'ffffff'; + labelColorHex = `#${sanitizeHexColor(params.labelColor, fallbackHex)}`; + } monthLabels.forEach((label) => { const tx = s(GRID_ORIGIN_X + (label.col - MONTH_LABEL_ROW_OFFSET) * TILE_WIDTH_HALF + 8); @@ -809,7 +812,7 @@ export function generateSVG( const text = `#${sanitizeHexColor(params.text, 'ffffff')}`; - const borderAttr = params.border ? `stroke="#${params.border}" stroke-width="2"` : ''; + const borderAttr = params.border ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` : ''; const sanitizedFont = sanitizeFont(params.font); const selectedFont = resolveFont(sanitizedFont); @@ -1606,7 +1609,7 @@ export function generateHeatmapSVG( const accent = `#${sanitizeHexColor(rawAccent, '00ffaa')}`; const text = `#${sanitizeHexColor(params.text, 'ffffff')}`; - const borderAttr = params.border ? `stroke="#${params.border}" stroke-width="2"` : ''; + const borderAttr = params.border ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` : ''; const sanitizedFont = sanitizeFont(params.font); const selectedFont = resolveFont(sanitizedFont); @@ -3128,7 +3131,7 @@ export function generateLanguagesSVG( const accent = `#${sanitizeHexColor(accentStr, '00ffaa')}`; const text = `#${sanitizeHexColor(params.text, 'ffffff')}`; - const borderAttr = params.border ? `stroke="#${params.border}" stroke-width="2"` : ''; + const borderAttr = params.border ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` : ''; const sanitizedFont = sanitizeFont(params.font); const selectedFont = resolveFont(sanitizedFont); From 660cc12e2e81c7ec5ea46eb07045da2c14b6cffe Mon Sep 17 00:00:00 2001 From: Diksha Dabhole Date: Sun, 21 Jun 2026 15:46:25 +0530 Subject: [PATCH 2/2] chore(svg): apply prettier formatting --- lib/svg/generator.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/svg/generator.ts b/lib/svg/generator.ts index 3c1cca1a6..6fb70b679 100644 --- a/lib/svg/generator.ts +++ b/lib/svg/generator.ts @@ -812,7 +812,9 @@ export function generateSVG( const text = `#${sanitizeHexColor(params.text, 'ffffff')}`; - const borderAttr = params.border ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` : ''; + const borderAttr = params.border + ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` + : ''; const sanitizedFont = sanitizeFont(params.font); const selectedFont = resolveFont(sanitizedFont); @@ -1609,7 +1611,9 @@ export function generateHeatmapSVG( const accent = `#${sanitizeHexColor(rawAccent, '00ffaa')}`; const text = `#${sanitizeHexColor(params.text, 'ffffff')}`; - const borderAttr = params.border ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` : ''; + const borderAttr = params.border + ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` + : ''; const sanitizedFont = sanitizeFont(params.font); const selectedFont = resolveFont(sanitizedFont); @@ -3131,7 +3135,9 @@ export function generateLanguagesSVG( const accent = `#${sanitizeHexColor(accentStr, '00ffaa')}`; const text = `#${sanitizeHexColor(params.text, 'ffffff')}`; - const borderAttr = params.border ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` : ''; + const borderAttr = params.border + ? `stroke="#${sanitizeHexColor(params.border, '000000')}" stroke-width="2"` + : ''; const sanitizedFont = sanitizeFont(params.font); const selectedFont = resolveFont(sanitizedFont);