Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions docs/VULNERABILITY_CATALOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ from each file's header comment, so this page cannot drift from the source.

## Totals

- **Test cases:** 124
- **Expected detections:** 124
- **`VULNERABLE:` markers:** 231 (individual lines a scanner should flag)
- **`SAFE:` markers:** 141 (lines a scanner must not flag — the false-positive control group)
- **Test cases:** 125
- **Expected detections:** 125
- **`VULNERABLE:` markers:** 233 (individual lines a scanner should flag)
- **`SAFE:` markers:** 142 (lines a scanner must not flag — the false-positive control group)
- **Languages:** 8 — dotenv, go, java, javascript, json, python, ruby, text
- **CWE categories:** 87 — 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-287, CWE-288, CWE-291, CWE-295, CWE-306, CWE-307, CWE-311, 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:** 88 — 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-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

## How coverage is scored

Expand Down Expand Up @@ -103,6 +103,7 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`.

| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
| Cleartext storage of sensitive information in a local file | [`cleartext-sensitive-storage.py`](../vulns/python/cleartext-sensitive-storage.py) | CWE-312 | high | yes | 2 vuln / 1 safe |
| Sensitive data sent over an unencrypted channel | [`cleartext-transmission.py`](../vulns/python/cleartext-transmission.py) | CWE-319 | high | yes | 5 vuln / 1 safe |
| Session cookie missing Secure flag over HTTPS | [`cookie-without-secure.py`](../vulns/python/cookie-without-secure.py) | CWE-614 | medium | yes | 3 vuln / 2 safe |
| CSRF via missing anti-CSRF token on state-changing POST | [`csrf-missing-token.py`](../vulns/python/csrf-missing-token.py) | CWE-352 | high | yes | 3 vuln / 1 safe |
Expand Down
33 changes: 29 additions & 4 deletions vulns/VULNERABILITY_CATALOG.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": 124,
"expected_detections": 124,
"vulnerable_markers": 231,
"safe_markers": 141,
"test_cases": 125,
"expected_detections": 125,
"vulnerable_markers": 233,
"safe_markers": 142,
"languages": [
"dotenv",
"go",
Expand Down Expand Up @@ -50,6 +50,7 @@
"CWE-306",
"CWE-307",
"CWE-311",
"CWE-312",
"CWE-319",
"CWE-321",
"CWE-326",
Expand Down Expand Up @@ -1569,6 +1570,30 @@
34
]
},
{
"id": "py-cleartext-sensitive-storage",
"file": "vulns/python/cleartext-sensitive-storage.py",
"title": "Cleartext storage of sensitive information in a local file",
"category": "python",
"language": "python",
"cwe": "CWE-312",
"cwes": [
"CWE-312"
],
"severity": "high",
"expected_detection": true,
"description": "Sensitive data (session tokens, passwords, API keys) is written",
"detection_target": "open(..., \"w\") / Path.write_text / json.dump / yaml.dump",
"safe_guard": "All code is wrapped in `if False:` (unreachable dead code). No",
"attribution": "line",
"vulnerable_lines": [
31,
39
],
"safe_lines": [
51
]
},
{
"id": "py-cleartext-transmission",
"file": "vulns/python/cleartext-transmission.py",
Expand Down
55 changes: 55 additions & 0 deletions vulns/python/cleartext-sensitive-storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
@id py-cleartext-sensitive-storage
@test-case Cleartext storage of sensitive information in a local file
@cwe CWE-312
@severity high
@language python
@expected-detection true
@description Sensitive data (session tokens, passwords, API keys) is written
to a local file in cleartext with no access restriction. Any
process with the app's user can read the file. The safe
counterpart encrypts the payload or stores the secret via a
restricted 0o600 file with key rotation. Detection target is a
secret-shaped value written to a filesystem sink with no
encryption step.
@safe-guard All code is wrapped in `if False:` (unreachable dead code). No
file is created; the secret literal is synthetic and protects
nothing.
@detection-target open(..., "w") / Path.write_text / json.dump / yaml.dump
where the payload contains a credential/token/session-shaped
value and the write mode is not restricted/encrypted.

NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
"""

import json
import os


def cache_session_token_vulnerable(session_id: str) -> None:
if False:
# VULNERABLE: CWE-312 - session token persisted in cleartext
with open("/tmp/internal/session.txt", "w") as fh: # noqa: S108
fh.write(session_id)
return None


def dump_config_vulnerable(api_key: str) -> None:
if False:
# VULNERABLE: CWE-312 - API key dumped to JSON cleartext
with open("config/runtime.json", "w") as fh:
json.dump({"api_key": api_key}, fh)
return None


def cache_session_token_safe(session_id: str) -> None:
"""Safe counterpart - the scanner should NOT flag this.

@expected-detection false
"""
if False:
# SAFE: restricted perms + only encrypted bytes persisted
fd = os.open("/tmp/internal/session.dat", os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
with os.fdopen(fd, "wb") as fh:
fh.write(b"encrypted-bytes-here")
return None
Loading