fix SVG Injection problem

This commit is contained in:
2026-07-17 13:35:55 +02:00
parent 8fb05b3f5b
commit b7c6c5df7b
3 changed files with 60 additions and 22 deletions
+19 -11
View File
@@ -1,5 +1,6 @@
const router = require('express').Router();
const axios = require('axios');
const { escapeSvg, safeColor } = require('../lib/sanitize');
router.get('/badge', async (req, res) => {
const {
@@ -16,7 +17,8 @@ router.get('/badge', async (req, res) => {
try {
// download icon SVG from SimpleIcons CDN
const iconUrl = `https://cdn.simpleicons.org/${icon}?viewbox=auto&size=${size}`;
const safeIcon = escapeSvg(icon);
const iconUrl = `https://cdn.simpleicons.org/${safeIcon}?viewbox=auto&size=${size}`;
const iconResponse = await axios.get(iconUrl, { responseType: 'text' });
if (iconResponse.status !== 200) {
return res.status(404).send('Icon not found');
@@ -33,6 +35,11 @@ router.get('/badge', async (req, res) => {
}
// Badge size
const safeLabel = escapeSvg(effectiveLabel);
const safeBgIcon = safeColor(bgicon, 'none');
const safeBgLabel = safeColor(bglabel, 'none');
const safeFontWeight = escapeSvg(fontweight);
const padding = 10;
const iconSize = parseInt(size);
const fontSize = Math.round(iconSize * 0.6);
@@ -63,6 +70,7 @@ router.get('/badge', async (req, res) => {
effectiveColor = "#222"; // fallback
}
}
effectiveColor = safeColor(effectiveColor, '#222');
// doboz magasság 5 pixellel nagyobb legyen az ikon méreténél
const iconSizeAndPadding = iconSize + 5;
@@ -71,14 +79,14 @@ router.get('/badge', async (req, res) => {
let width, height, iconGroup, textElem;
const fontFamily = "Verdana,Geneva,DejaVu Sans,sans-serif";
const fontWeight = fontweight; // paraméterből
const fontWeight = safeFontWeight; // paraméterből
if (labelpos === 'left') {
// Külön dobozok: padding csak a széleken kell, a dobozokon belül nem!
textElem = `<rect x="0" y="0" width="${textWidth}" height="${iconBoxHeight}" rx="${radius}" fill="${bglabel}"/>
<text x="${textWidth / 2}" y="${iconBoxHeight / 2}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${effectiveColor}" text-anchor="middle" dominant-baseline="middle">${effectiveLabel}</text>`;
textElem = `<rect x="0" y="0" width="${textWidth}" height="${iconBoxHeight}" rx="${radius}" fill="${safeBgLabel}"/>
<text x="${textWidth / 2}" y="${iconBoxHeight / 2}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${effectiveColor}" text-anchor="middle" dominant-baseline="middle">${safeLabel}</text>`;
iconGroup = `
<rect x="${textWidth}" y="0" width="${iconBoxWidth + 5}" height="${iconBoxHeight}" rx="${radius}" fill="${bgicon}"/>
<rect x="${textWidth}" y="0" width="${iconBoxWidth + 5}" height="${iconBoxHeight}" rx="${radius}" fill="${safeBgIcon}"/>
<g transform="translate(${textWidth + (5 / 2)}, ${(iconBoxHeight - iconSize) / 2})">${iconSVG}</g>
`;
} else if (labelpos === 'above' || labelpos === 'below') {
@@ -94,9 +102,9 @@ router.get('/badge', async (req, res) => {
height = iconSizeAndPadding + textPadding + labelRectHeight;
// Label háttér
const labelRect = `<rect x="0" y="${labelRectY}" width="${width}" height="${labelRectHeight}" rx="${radius}" fill="${bglabel}"/>`;
const labelRect = `<rect x="0" y="${labelRectY}" width="${width}" height="${labelRectHeight}" rx="${radius}" fill="${safeBgLabel}"/>`;
// Ikon háttér
const iconRect = `<rect x="0" y="${iconRectY}" width="${width}" height="${iconSize + 5}" rx="${radius}" fill="${bgicon}"/>`;
const iconRect = `<rect x="0" y="${iconRectY}" width="${width}" height="${iconSize + 5}" rx="${radius}" fill="${safeBgIcon}"/>`;
// Szöveg
const textY = labelpos === 'above'
@@ -104,7 +112,7 @@ router.get('/badge', async (req, res) => {
: labelRectY + 5 + labelRectHeight / 2;
textElem = `
${labelRect}
<text x="${width / 2}" y="${textY}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${effectiveColor}" text-anchor="middle" dominant-baseline="middle">${effectiveLabel}</text>
<text x="${width / 2}" y="${textY}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${effectiveColor}" text-anchor="middle" dominant-baseline="middle">${safeLabel}</text>
`;
// Ikon
@@ -115,11 +123,11 @@ router.get('/badge', async (req, res) => {
} else {
// Alapértelmezett: ikon balra, szöveg jobbra (függőleges közép)
iconGroup = `
<rect x="0" y="0" width="${iconBoxWidth}" height="${iconBoxHeight}" rx="${radius}" fill="${bgicon}"/>
<rect x="0" y="0" width="${iconBoxWidth}" height="${iconBoxHeight}" rx="${radius}" fill="${safeBgIcon}"/>
<g transform="translate(${(iconBoxWidth - iconViewBoxWidth) / 2}, ${(iconBoxHeight - iconViewBoxHeight) / 2})">${iconSVG}</g>
`;
textElem = `<rect x="${iconBoxWidth}" y="0" width="${textWidth}" height="${iconBoxHeight}" rx="${radius}" fill="${bglabel}"/>
<text x="${iconBoxWidth + textWidth / 2}" y="${iconBoxHeight / 2}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${effectiveColor}" text-anchor="middle" dominant-baseline="middle">${effectiveLabel}</text>`;
textElem = `<rect x="${iconBoxWidth}" y="0" width="${textWidth}" height="${iconBoxHeight}" rx="${radius}" fill="${safeBgLabel}"/>
<text x="${iconBoxWidth + textWidth / 2}" y="${iconBoxHeight / 2}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${effectiveColor}" text-anchor="middle" dominant-baseline="middle">${safeLabel}</text>`;
}
// SVG badge string összefűzéssel, szöveg árnyékkal