From 09e2d3fe39472e21257bb46cfb6178ae92583ccd Mon Sep 17 00:00:00 2001 From: CSTRSK Date: Sun, 9 Aug 2026 09:02:57 +0000 Subject: [PATCH] test-cases: add CWE-195 (go) --- docs/VULNERABILITY_CATALOG.md | 11 +++--- vulns/VULNERABILITY_CATALOG.json | 35 +++++++++++++++-- vulns/go/cwe-195-go.go | 66 ++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 vulns/go/cwe-195-go.go diff --git a/docs/VULNERABILITY_CATALOG.md b/docs/VULNERABILITY_CATALOG.md index 5763d34..2aab14d 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:** 127 (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-195, 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 ## How coverage is scored @@ -27,6 +27,7 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`. | Test case | File | CWE | Severity | Expected | Markers | |---|---|---|---|---|---| | OS command injection via exec.Command with a shell | [`cmd-injection-exec.go`](../vulns/go/cmd-injection-exec.go) | CWE-78 | critical | yes | 2 vuln / 1 safe | +| Unsigned to signed integer conversion leading to negative length | [`cwe-195-go.go`](../vulns/go/cwe-195-go.go) | CWE-195 | high | yes | 4 vuln / 1 safe | | Integer overflow and unchecked narrowing conversion | [`integer-overflow.go`](../vulns/go/integer-overflow.go) | CWE-190 | medium | yes | 2 vuln / 3 safe | | SQL injection via fmt.Sprintf | [`sqli-fmt-sprintf.go`](../vulns/go/sqli-fmt-sprintf.go) | CWE-89 | critical | yes | 2 vuln / 1 safe | | Server-side request forgery via http.Get on a user-supplied URL | [`ssrf-http-get.go`](../vulns/go/ssrf-http-get.go) | CWE-918 | high | yes | 2 vuln / 2 safe | diff --git a/vulns/VULNERABILITY_CATALOG.json b/vulns/VULNERABILITY_CATALOG.json index 153fdaf..34eca9a 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": 127, + "safe_markers": 74, "languages": [ "dotenv", "go", @@ -36,6 +36,7 @@ "CWE-113", "CWE-117", "CWE-190", + "CWE-195", "CWE-201", "CWE-209", "CWE-256", @@ -99,6 +100,32 @@ 46 ] }, + { + "id": "go-cwe195-unsigned-to-signed", + "file": "vulns/go/cwe-195-go.go", + "title": "Unsigned to signed integer conversion leading to negative length", + "category": "go", + "language": "go", + "cwe": "CWE-195", + "cwes": [ + "CWE-195" + ], + "severity": "high", + "expected_detection": true, + "description": "User-controlled unsigned integer is converted to a signed", + "detection_target": "Taint flow from request input into a signed integer", + "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`", + "attribution": "line", + "vulnerable_lines": [ + 31, + 34, + 43, + 46 + ], + "safe_lines": [ + 57 + ] + }, { "id": "go-integer-overflow", "file": "vulns/go/integer-overflow.go", diff --git a/vulns/go/cwe-195-go.go b/vulns/go/cwe-195-go.go new file mode 100644 index 0000000..f7190d2 --- /dev/null +++ b/vulns/go/cwe-195-go.go @@ -0,0 +1,66 @@ +// @id go-cwe195-unsigned-to-signed +// @test-case Unsigned to signed integer conversion leading to negative length +// @cwe CWE-195 +// @severity high +// @language go +// @expected-detection true +// @description User-controlled unsigned integer is converted to a signed +// integer without bounds checking, resulting in a negative value +// that is used as a length parameter in a slice operation, +// potentially causing a panic or out-of-bounds access. +// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore` +// build tag; no code is ever executed. +// @detection-target Taint flow from request input into a signed integer +// conversion used as a slice length or array index. +// +// NEVER RUN IN PRODUCTION — intentional test case for scanner validation. + +//go:build ignore + +package vulns + +import ( + "net/http" + "strconv" +) + +func sliceVulnerable(r *http.Request) []byte { + if neverRun { + unsignedLen := r.URL.Query().Get("len") // SOURCE: attacker-controlled + u, _ := strconv.ParseUint(unsignedLen, 10, 32) + // VULNERABLE: CWE-195 - unsigned to signed conversion without bounds check + signedLen := int(u) + data := make([]byte, 100) + return data[:signedLen] // VULNERABLE: CWE-195 - negative length causes panic + } + return nil +} + +func indexVulnerable(r *http.Request) byte { + if neverRun { + unsignedIdx := r.FormValue("idx") // SOURCE + u, _ := strconv.ParseUint(unsignedIdx, 10, 32) + // VULNERABLE: CWE-195 - unsigned to signed conversion without bounds check + signedIdx := int(u) + data := []byte{1, 2, 3, 4, 5} + return data[signedIdx] // VULNERABLE: CWE-195 - negative index causes panic + } + return 0 +} + +// sliceSafe is the safe counterpart — the scanner should NOT flag this. +// @expected-detection false +func sliceSafe(r *http.Request) []byte { + if neverRun { + unsignedLen := r.URL.Query().Get("len") // SOURCE + u, _ := strconv.ParseUint(unsignedLen, 10, 32) + // SAFE: explicit bounds check before conversion + if u > 100 { + return nil + } + signedLen := int(u) + data := make([]byte, 100) + return data[:signedLen] + } + return nil +} \ No newline at end of file