From 014a81d14e79bdc2f561a9ee949c8488e42ae29c Mon Sep 17 00:00:00 2001 From: Swordoffik <319625310+Swordoffik@users.noreply.github.com> Date: Sat, 22 Aug 2026 00:14:50 +0200 Subject: [PATCH] test: add missing HttpOnly cookie fixture --- docs/VULNERABILITY_CATALOG.md | 11 ++--- vulns/VULNERABILITY_CATALOG.json | 32 ++++++++++++-- vulns/javascript/cookie-without-httponly.js | 46 +++++++++++++++++++++ 3 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 vulns/javascript/cookie-without-httponly.js diff --git a/docs/VULNERABILITY_CATALOG.md b/docs/VULNERABILITY_CATALOG.md index 01acd4c..be2ab1c 100644 --- a/docs/VULNERABILITY_CATALOG.md +++ b/docs/VULNERABILITY_CATALOG.md @@ -7,12 +7,12 @@ from each file's header comment, so this page cannot drift from the source. ## Totals -- **Test cases:** 127 -- **Expected detections:** 127 -- **`VULNERABLE:` markers:** 236 (individual lines a scanner should flag) -- **`SAFE:` markers:** 144 (lines a scanner must not flag — the false-positive control group) +- **Test cases:** 128 +- **Expected detections:** 128 +- **`VULNERABLE:` markers:** 237 (individual lines a scanner should flag) +- **`SAFE:` markers:** 145 (lines a scanner must not flag — the false-positive control group) - **Languages:** 8 — dotenv, go, java, javascript, json, python, ruby, text -- **CWE categories:** 89 — CWE-20, CWE-22, CWE-78, CWE-79, CWE-89, CWE-90, CWE-94, CWE-95, CWE-113, CWE-117, CWE-129, CWE-190, CWE-201, CWE-203, CWE-208, CWE-209, CWE-256, CWE-285, CWE-287, CWE-288, CWE-291, CWE-295, CWE-306, CWE-307, CWE-311, CWE-312, CWE-319, CWE-321, CWE-326, CWE-327, CWE-329, CWE-330, CWE-338, CWE-345, CWE-346, CWE-347, CWE-352, CWE-362, CWE-377, CWE-384, CWE-400, CWE-409, CWE-434, CWE-441, CWE-460, CWE-472, CWE-475, CWE-480, CWE-488, CWE-489, CWE-502, CWE-506, CWE-509, CWE-512, CWE-521, CWE-522, CWE-525, CWE-532, CWE-598, CWE-601, CWE-602, CWE-611, CWE-613, CWE-614, CWE-620, CWE-639, CWE-640, CWE-643, CWE-681, CWE-693, CWE-732, CWE-759, CWE-776, CWE-798, CWE-835, CWE-862, CWE-863, CWE-915, CWE-916, CWE-918, CWE-922, CWE-942, CWE-943, CWE-1021, CWE-1236, CWE-1321, CWE-1333, CWE-1336, CWE-1357 +- **CWE categories:** 90 — CWE-20, CWE-22, CWE-78, CWE-79, CWE-89, CWE-90, CWE-94, CWE-95, CWE-113, CWE-117, CWE-129, CWE-190, CWE-201, CWE-203, CWE-208, CWE-209, CWE-256, CWE-285, CWE-287, CWE-288, CWE-291, CWE-295, CWE-306, CWE-307, CWE-311, CWE-312, CWE-319, CWE-321, CWE-326, CWE-327, CWE-329, CWE-330, CWE-338, CWE-345, CWE-346, CWE-347, CWE-352, CWE-362, CWE-377, CWE-384, CWE-400, CWE-409, CWE-434, CWE-441, CWE-460, CWE-472, CWE-475, CWE-480, CWE-488, CWE-489, CWE-502, CWE-506, CWE-509, CWE-512, CWE-521, CWE-522, CWE-525, CWE-532, CWE-598, CWE-601, CWE-602, CWE-611, CWE-613, CWE-614, CWE-620, CWE-639, CWE-640, CWE-643, CWE-681, CWE-693, CWE-732, CWE-759, CWE-776, CWE-798, CWE-835, CWE-862, CWE-863, CWE-915, CWE-916, CWE-918, CWE-922, CWE-942, CWE-943, CWE-1004, CWE-1021, CWE-1236, CWE-1321, CWE-1333, CWE-1336, CWE-1357 ## How coverage is scored @@ -54,6 +54,7 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`. | Privileged export exposed through an unauthenticated alternate route | [`alternate-path-auth-bypass.js`](../vulns/javascript/alternate-path-auth-bypass.js) | CWE-288 | high | yes | 1 vuln / 1 safe | | Privileged action trusts a client-supplied access flag | [`client-side-admin-enforcement.js`](../vulns/javascript/client-side-admin-enforcement.js) | CWE-602 | high | yes | 1 vuln / 1 safe | | Sensitive session cookie without the Secure attribute | [`cookie-security-flags.js`](../vulns/javascript/cookie-security-flags.js) | CWE-614 | medium | yes | 1 vuln / 1 safe | +| Sensitive session cookie without the HttpOnly attribute | [`cookie-without-httponly.js`](../vulns/javascript/cookie-without-httponly.js) | CWE-1004 | medium | yes | 1 vuln / 1 safe | | Credentialed CORS configured with a wildcard origin | [`cors-wildcard-credentials.js`](../vulns/javascript/cors-wildcard-credentials.js) | CWE-942 | high | yes | 1 vuln / 1 safe | | CSRF via missing anti-CSRF token on state-changing POST | [`csrf-missing-token.js`](../vulns/javascript/csrf-missing-token.js) | CWE-352 | high | yes | 3 vuln / 1 safe | | Resource cleanup not performed on error path | [`cwe-460-javascript.js`](../vulns/javascript/cwe-460-javascript.js) | CWE-460 | medium | yes | 1 vuln / 1 safe | diff --git a/vulns/VULNERABILITY_CATALOG.json b/vulns/VULNERABILITY_CATALOG.json index 8fb4128..0028a4d 100644 --- a/vulns/VULNERABILITY_CATALOG.json +++ b/vulns/VULNERABILITY_CATALOG.json @@ -2,10 +2,10 @@ "schema": "threatcrush-testbed-catalog/1", "note": "Generated by scripts/generate-catalog.py \u2014 do not edit by hand.", "totals": { - "test_cases": 127, - "expected_detections": 127, - "vulnerable_markers": 236, - "safe_markers": 144, + "test_cases": 128, + "expected_detections": 128, + "vulnerable_markers": 237, + "safe_markers": 145, "languages": [ "dotenv", "go", @@ -109,6 +109,7 @@ "CWE-922", "CWE-942", "CWE-943", + "CWE-1004", "CWE-1021", "CWE-1236", "CWE-1321", @@ -546,6 +547,29 @@ 31 ] }, + { + "id": "js-cookie-without-httponly", + "file": "vulns/javascript/cookie-without-httponly.js", + "title": "Sensitive session cookie without the HttpOnly attribute", + "category": "javascript", + "language": "javascript", + "cwe": "CWE-1004", + "cwes": [ + "CWE-1004" + ], + "severity": "medium", + "expected_detection": true, + "description": "A session token is placed in a browser cookie without HttpOnly,", + "detection_target": "A security-sensitive cookie configured without httpOnly.", + "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. The", + "attribution": "line", + "vulnerable_lines": [ + 24 + ], + "safe_lines": [ + 36 + ] + }, { "id": "js-cors-wildcard-credentials", "file": "vulns/javascript/cors-wildcard-credentials.js", diff --git a/vulns/javascript/cookie-without-httponly.js b/vulns/javascript/cookie-without-httponly.js new file mode 100644 index 0000000..dd02c0b --- /dev/null +++ b/vulns/javascript/cookie-without-httponly.js @@ -0,0 +1,46 @@ +/** + * @id js-cookie-without-httponly + * @test-case Sensitive session cookie without the HttpOnly attribute + * @cwe CWE-1004 + * @severity medium + * @language javascript + * @expected-detection true + * @description A session token is placed in a browser cookie without HttpOnly, + * allowing injected client-side script to read the credential. + * @safe-guard Wrapped in if (false) — the body is unreachable dead code. The + * fixture performs no network, filesystem, or process operations. + * @detection-target A security-sensitive cookie configured without httpOnly. + */ + +'use strict'; + +// NEVER RUN IN PRODUCTION — intentional test case for scanner validation. +function setSessionCookieVulnerable(req, res) { + if (false) { + const sessionToken = req.user.sessionToken; + res.cookie('session', sessionToken, { + secure: true, + sameSite: 'lax', + }); // VULNERABLE: CWE-1004 — HttpOnly is omitted + } +} + +/** + * Safe counterpart — the scanner should NOT flag this. + * @expected-detection false + */ +function setSessionCookieSafe(req, res) { + if (false) { + const sessionToken = req.user.sessionToken; + res.cookie('session', sessionToken, { + httpOnly: true, // SAFE: browser scripts cannot read the session cookie + secure: true, + sameSite: 'lax', + }); + } +} + +module.exports = { + setSessionCookieVulnerable, + setSessionCookieSafe, +};