diff --git a/tests/integration.js b/tests/integration.js index 9d58601..368839f 100644 --- a/tests/integration.js +++ b/tests/integration.js @@ -516,6 +516,50 @@ async function cleanup() { } } + // ───────────────────────────────────────────────────────────────────────────── + // 16. Безопасность — XSS и спецсимволы в comment + // ───────────────────────────────────────────────────────────────────────────── + console.log('\n── 16. Безопасность: XSS в comment ──'); + + { + const xssPayload = ''; + const csrf = await getCsrfFromIndex(userAgent); + const res = await userAgent.post('/add').type('form') + .send({ value: '5.5.5.5', comment: xssPayload, _csrf: csrf }); + // Запись могла добавиться или нет (зависит от валидации comment) + const err = getRedirectParam(res, 'error'); + + // Если добавилась — проверяем что скрипт не выполняется в HTML + const page = await userAgent.get('/'); + const rawScript = page.text.includes(''); + log(!rawScript, 'security: XSS в comment — скрипт не рендерится в HTML', + rawScript ? 'RAW SCRIPT FOUND — XSS!' : `escaped или отклонено (err=${err})`); + + // Чистим + await pool.query( + `UPDATE whitelist_entries SET deleted_at = NOW(), deleted_by = 'test-cleanup' + WHERE value_cidr = '5.5.5.5/32' AND deleted_at IS NULL` + ); + } + + // ───────────────────────────────────────────────────────────────────────────── + // 17. Rate-limiter — превысить mutationLimiter (30 POST/min) + // ───────────────────────────────────────────────────────────────────────────── + console.log('\n── 17. Rate-limiter ──'); + + { + // Отправляем 35 POST /add подряд с заведомо невалидным CIDR (быстро) + // Rate-limiter (30/min) должен сработать и вернуть 429 + let got429 = false; + for (let i = 0; i < 35; i++) { + const csrf = await getCsrfFromIndex(userAgent); + const res = await userAgent.post('/add').type('form') + .send({ value: 'not-an-ip', comment: `rate ${i}`, _csrf: csrf }); + if (res.status === 429) { got429 = true; break; } + } + log(got429, 'rate-limiter: POST /add → 429 после 30 запросов'); + } + // ───────────────────────────────────────────────────────────────────────────── // Cleanup // ─────────────────────────────────────────────────────────────────────────────