diff --git a/docs/VULNERABILITY_CATALOG.md b/docs/VULNERABILITY_CATALOG.md index 5763d34..84b6d95 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:** 62 -- **Expected detections:** 62 -- **`VULNERABLE:` markers:** 123 (individual lines a scanner should flag) -- **`SAFE:` markers:** 73 (lines a scanner must not flag — the false-positive control group) +- **Test cases:** 63 +- **Expected detections:** 63 +- **`VULNERABLE:` markers:** 124 (individual lines a scanner should flag) +- **`SAFE:` markers:** 74 (lines a scanner must not flag — the false-positive control group) - **Languages:** 8 — dotenv, go, java, javascript, json, python, ruby, text -- **CWE categories:** 46 — CWE-20, CWE-22, CWE-78, CWE-79, CWE-89, CWE-90, CWE-95, CWE-113, CWE-117, CWE-190, CWE-201, CWE-209, CWE-256, CWE-295, CWE-321, CWE-327, CWE-330, CWE-338, CWE-346, CWE-347, CWE-352, CWE-362, CWE-377, CWE-384, CWE-489, CWE-502, CWE-506, CWE-532, CWE-601, CWE-611, CWE-614, CWE-639, CWE-643, CWE-681, CWE-759, CWE-798, CWE-862, CWE-915, CWE-918, CWE-942, CWE-943, CWE-1236, CWE-1321, CWE-1333, CWE-1336, CWE-1357 +- **CWE categories:** 47 — CWE-20, CWE-22, CWE-78, CWE-79, CWE-89, CWE-90, CWE-95, CWE-113, CWE-117, CWE-190, CWE-201, CWE-209, CWE-252, CWE-256, CWE-295, CWE-321, CWE-327, CWE-330, CWE-338, CWE-346, CWE-347, CWE-352, CWE-362, CWE-377, CWE-384, CWE-489, CWE-502, CWE-506, CWE-532, CWE-601, CWE-611, CWE-614, CWE-639, CWE-643, CWE-681, CWE-759, CWE-798, CWE-862, CWE-915, CWE-918, CWE-942, CWE-943, CWE-1236, CWE-1321, CWE-1333, CWE-1336, CWE-1357 ## How coverage is scored @@ -63,6 +63,7 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`. | SQL injection via string concatenation | [`sqli-raw-concat.js`](../vulns/javascript/sqli-raw-concat.js) | CWE-89 | critical | yes | 2 vuln / 1 safe | | Server-side request forgery via user-supplied URL | [`ssrf-request-user-url.js`](../vulns/javascript/ssrf-request-user-url.js) | CWE-918 | high | yes | 2 vuln / 2 safe | | TLS certificate validation disabled on an HTTPS agent | [`tls-reject-unauthorized-false.js`](../vulns/javascript/tls-reject-unauthorized-false.js) | CWE-295 | high | yes | 1 vuln / 1 safe | +| Unchecked error from file read operation leads to unhandled exception | [`cwe-252-javascript.js`](../vulns/javascript/cwe-252-javascript.js) | CWE-252 | medium | yes | 1 vuln / 1 safe | | Reflected XSS via innerHTML | [`xss-dom-innerHTML.js`](../vulns/javascript/xss-dom-innerHTML.js) | CWE-79 | high | yes | 2 vuln / 1 safe | | Code injection via eval() of user input | [`xss-eval-user-input.js`](../vulns/javascript/xss-eval-user-input.js) | CWE-95 | critical | yes | 3 vuln / 1 safe | diff --git a/vulns/VULNERABILITY_CATALOG.json b/vulns/VULNERABILITY_CATALOG.json index 153fdaf..85fde04 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": 62, - "expected_detections": 62, - "vulnerable_markers": 123, - "safe_markers": 73, + "test_cases": 63, + "expected_detections": 63, + "vulnerable_markers": 124, + "safe_markers": 74, "languages": [ "dotenv", "go", @@ -38,6 +38,7 @@ "CWE-190", "CWE-201", "CWE-209", + "CWE-252", "CWE-256", "CWE-295", "CWE-321", @@ -344,6 +345,29 @@ 55 ] }, + { + "id": "js-unchecked-error-handling", + "file": "vulns/javascript/cwe-252-javascript.js", + "title": "Unchecked error from file read operation leads to unhandled exception", + "category": "javascript", + "language": "javascript", + "cwe": "CWE-252", + "cwes": [ + "CWE-252" + ], + "severity": "medium", + "expected_detection": true, + "description": "A file read operation is performed without checking the error", + "detection_target": "Callback functions that ignore the error parameter", + "safe_guard": "Both handlers are unreachable behind if (false), and the file", + "attribution": "line", + "vulnerable_lines": [ + 24 + ], + "safe_lines": [ + 39 + ] + }, { "id": "js-hardcoded-crypto-key", "file": "vulns/javascript/hardcoded-crypto-key.js", diff --git a/vulns/javascript/cwe-252-javascript.js b/vulns/javascript/cwe-252-javascript.js new file mode 100644 index 0000000..f924db1 --- /dev/null +++ b/vulns/javascript/cwe-252-javascript.js @@ -0,0 +1,43 @@ +/** + * @id js-unchecked-error-handling + * @test-case Unchecked error from file read operation leads to unhandled exception + * @cwe CWE-252 + * @severity medium + * @language javascript + * @expected-detection true + * @description A file read operation is performed without checking the error + * parameter of the callback, leading to potential unhandled + * exceptions or undefined behavior when the file does not exist. + * @safe-guard Both handlers are unreachable behind if (false), and the file + * paths are inert test doubles supplied by a scanner harness. + * @detection-target Callback functions that ignore the error parameter + * in asynchronous I/O operations. + */ + +'use strict'; + +const fs = require('fs'); + +function readFileVulnerable(filePath, callback) { + if (false) { + fs.readFile(filePath, 'utf8', (err, data) => { + // VULNERABLE: CWE-252 - error parameter is ignored + callback(data); + }); + } +} + +/** Safe counterpart. @expected-detection false */ +function readFileSafe(filePath, callback) { + if (false) { + fs.readFile(filePath, 'utf8', (err, data) => { + if (err) { + callback(err, null); + return; + } + callback(null, data); + }); // SAFE: error is properly checked and propagated + } +} + +module.exports = { readFileVulnerable, readFileSafe }; \ No newline at end of file