fix(api): sanitize og-story level input (#219)

This commit is contained in:
Lawyered
2026-02-21 18:19:01 -05:00
committed by GitHub
parent e1b9e9e8a9
commit 4365626df3
2 changed files with 54 additions and 1 deletions

View File

@@ -25,12 +25,17 @@ const LEVEL_LABELS = {
low: 'LOW RISK',
};
function normalizeLevel(rawLevel) {
const level = String(rawLevel || '').toLowerCase();
return Object.prototype.hasOwnProperty.call(LEVEL_COLORS, level) ? level : 'normal';
}
export default function handler(req, res) {
const url = new URL(req.url, `https://${req.headers.host}`);
const countryCode = (url.searchParams.get('c') || '').toUpperCase();
const type = url.searchParams.get('t') || 'ciianalysis';
const score = url.searchParams.get('s');
const level = url.searchParams.get('l') || 'normal';
const level = normalizeLevel(url.searchParams.get('l'));
const countryName = COUNTRY_NAMES[countryCode] || countryCode || 'Global';
const levelColor = LEVEL_COLORS[level] || '#eab308';

48
api/og-story.test.mjs Normal file
View File

@@ -0,0 +1,48 @@
import { strict as assert } from 'node:assert';
import test from 'node:test';
import handler from './og-story.js';
function renderOgStory(query = '') {
const req = {
url: `https://worldmonitor.app/api/og-story${query ? `?${query}` : ''}`,
headers: { host: 'worldmonitor.app' },
};
let statusCode = 0;
let body = '';
const headers = {};
const res = {
setHeader(name, value) {
headers[String(name).toLowerCase()] = String(value);
},
status(code) {
statusCode = code;
return this;
},
send(payload) {
body = String(payload);
},
};
handler(req, res);
return { statusCode, body, headers };
}
test('normalizes unsupported level values to prevent SVG script injection', () => {
const injectedLevel = encodeURIComponent('</text><script>alert(1)</script><text>');
const response = renderOgStory(`c=US&s=50&l=${injectedLevel}`);
assert.equal(response.statusCode, 200);
assert.equal(/<script/i.test(response.body), false);
assert.match(response.body, />NORMAL<\/text>/);
});
test('uses a known level when it is allowlisted', () => {
const response = renderOgStory('c=US&s=88&l=critical');
assert.equal(response.statusCode, 200);
assert.match(response.body, />CRITICAL<\/text>/);
assert.match(response.body, /#ef4444/);
});