Skip to content
Closed
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:** 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-256, CWE-260, 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

Expand Down Expand Up @@ -71,6 +71,7 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`.
| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
| CSV formula injection from untrusted spreadsheet cells | [`csv-formula-injection.py`](../vulns/python/csv-formula-injection.py) | CWE-1236 | medium | yes | 1 vuln / 1 safe |
| Password stored in world-readable configuration file | [`cwe-260-python.py`](../vulns/python/cwe-260-python.py) | CWE-260 | high | yes | 1 vuln / 1 safe |
| Excessive user-record exposure in an API response | [`excessive-data-exposure.py`](../vulns/python/excessive-data-exposure.py) | CWE-201 | high | yes | 1 vuln / 1 safe |
| Flask debug mode enabled in application configuration | [`flask-debug-enabled.py`](../vulns/python/flask-debug-enabled.py) | CWE-489 | high | yes | 1 vuln / 1 safe |
| Hardcoded secret used to configure session signing | [`hardcoded-session-secret.py`](../vulns/python/hardcoded-session-secret.py) | CWE-798 | high | yes | 1 vuln / 1 safe |
Expand Down
32 changes: 28 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": 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",
Expand Down Expand Up @@ -39,6 +39,7 @@
"CWE-201",
"CWE-209",
"CWE-256",
"CWE-260",
"CWE-295",
"CWE-321",
"CWE-327",
Expand Down Expand Up @@ -791,6 +792,29 @@
40
]
},
{
"id": "py-cwe260-password-in-config",
"file": "vulns/python/cwe-260-python.py",
"title": "Password stored in world-readable configuration file",
"category": "python",
"language": "python",
"cwe": "CWE-260",
"cwes": [
"CWE-260"
],
"severity": "high",
"expected_detection": true,
"description": "Application writes a plaintext password to a configuration file",
"detection_target": "Taint flow from request input into file write operation",
"safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
"attribution": "line",
"vulnerable_lines": [
29
],
"safe_lines": [
37
]
},
{
"id": "py-excessive-data-exposure",
"file": "vulns/python/excessive-data-exposure.py",
Expand Down
38 changes: 38 additions & 0 deletions vulns/python/cwe-260-python.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
@id py-cwe260-password-in-config
@test-case Password stored in world-readable configuration file
@cwe CWE-260
@severity high
@language python
@expected-detection true
@description Application writes a plaintext password to a configuration file
using default file permissions (0644), making it readable by any
local user. The password is sourced from an untrusted request
parameter and persisted without restricting file access.
@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
writes only to an in-memory StringIO object and never to disk.
@detection-target Taint flow from request input into file write operation
without setting restrictive permissions (e.g., 0600).

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


if False:
import os
import io

def save_config_vulnerable(request):
password = request.form["password"] # SOURCE: attacker-controlled
config_path = "/tmp/app_config.conf" # .invalid path, never executed
with open(config_path, "w") as config_file:
config_file.write(f"password={password}\n") # VULNERABLE: CWE-260
return "config saved"

def save_config_safe(request):
password = request.form["password"]
config_path = "/tmp/app_config_safe.conf" # .invalid path, never executed
fd = os.open(config_path, os.O_WRONLY | os.O_CREAT, 0o600)
with os.fdopen(fd, "w") as config_file:
config_file.write(f"password={password}\n") # SAFE: restrictive permissions
return "config saved" # @expected-detection false
Loading