boti-tripwire 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: boti-tripwire
3
+ Version: 0.1.0
4
+ Summary: Zero-day security scanner for the Boti workspace
5
+ Author-email: Luis Valverde <lvalverdeb@gmail.com>
6
+ License-Expression: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Security
14
+ Requires-Python: >=3.13
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: boti>=1.0.0
17
+
18
+ # tripwire
19
+
20
+ Zero-day security scanner for the Boti workspace.
21
+
22
+ Maps every finding to a CWE from the 2025 CWE Top 25, OWASP Top 10:2025, and known
23
+ Python zero-day exploit patterns (pickle bypass CVE-2026-56315, PyYAML shadow
24
+ vulnerability CVE-2026-24009, LangChain SSTI CVE-2025-68664, dependency confusion
25
+ CVE-2025-61774, and more — see the CWE reference printed at the end of every
26
+ text-mode report). 52 checks total: most are AST-based (won't false-positive on a
27
+ dangerous call mentioned in a docstring or comment); the rest are line-regex checks
28
+ for surface-syntax patterns that don't need full parsing.
29
+
30
+ ## Usage
31
+
32
+ ```bash
33
+ uv run tripwire
34
+ uv run tripwire --json > report.json
35
+ uv run tripwire -q
36
+ uv run tripwire --fail-on critical
37
+ uv run tripwire --package my-lib=my-lib/src/my_lib
38
+ ```
39
+
40
+ Exit codes: `0` (no findings at or above `--fail-on`), `1` (one or more).
41
+
42
+ ### Options
43
+
44
+ | Flag | Default | Description |
45
+ | --- | --- | --- |
46
+ | `--json` | off | Machine-readable output |
47
+ | `--quiet` / `-q` | off | Suppress the banner |
48
+ | `--fail-on` | `high` | Severity threshold (`critical`\|`high`\|`medium`\|`low`\|`info`) for the exit code |
49
+ | `--package NAME=PATH` | — | Add or override a scan target package (repeatable) |
50
+
51
+ By default, tripwire scans `boti`, `boti-data`, `boti-dask`, and itself.
52
+
53
+ ## Design
54
+
55
+ - `tripwire.models` — the `Finding` dataclass and severity ordering.
56
+ - `tripwire.config` — workspace-root discovery and the default package registry.
57
+ - `tripwire.ast_helpers` — shared AST/text-matching helpers used across checks.
58
+ - `tripwire.scanner` — file discovery and reading.
59
+ - `tripwire.checks.ast_checks` — checks that walk the parsed AST (won't match
60
+ a dangerous call mentioned in a docstring or string literal).
61
+ - `tripwire.checks.text_checks` — checks that scan raw source lines for
62
+ surface-syntax patterns.
63
+ - `tripwire.checks.manifest_checks` — checks over dependency manifests
64
+ (`pyproject.toml`, `requirements.txt`, etc.), not Python source.
65
+ - `tripwire.reporting` — text/JSON report rendering.
66
+ - `tripwire.cli` — argument parsing and the scan loop.
@@ -0,0 +1,49 @@
1
+ # tripwire
2
+
3
+ Zero-day security scanner for the Boti workspace.
4
+
5
+ Maps every finding to a CWE from the 2025 CWE Top 25, OWASP Top 10:2025, and known
6
+ Python zero-day exploit patterns (pickle bypass CVE-2026-56315, PyYAML shadow
7
+ vulnerability CVE-2026-24009, LangChain SSTI CVE-2025-68664, dependency confusion
8
+ CVE-2025-61774, and more — see the CWE reference printed at the end of every
9
+ text-mode report). 52 checks total: most are AST-based (won't false-positive on a
10
+ dangerous call mentioned in a docstring or comment); the rest are line-regex checks
11
+ for surface-syntax patterns that don't need full parsing.
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ uv run tripwire
17
+ uv run tripwire --json > report.json
18
+ uv run tripwire -q
19
+ uv run tripwire --fail-on critical
20
+ uv run tripwire --package my-lib=my-lib/src/my_lib
21
+ ```
22
+
23
+ Exit codes: `0` (no findings at or above `--fail-on`), `1` (one or more).
24
+
25
+ ### Options
26
+
27
+ | Flag | Default | Description |
28
+ | --- | --- | --- |
29
+ | `--json` | off | Machine-readable output |
30
+ | `--quiet` / `-q` | off | Suppress the banner |
31
+ | `--fail-on` | `high` | Severity threshold (`critical`\|`high`\|`medium`\|`low`\|`info`) for the exit code |
32
+ | `--package NAME=PATH` | — | Add or override a scan target package (repeatable) |
33
+
34
+ By default, tripwire scans `boti`, `boti-data`, `boti-dask`, and itself.
35
+
36
+ ## Design
37
+
38
+ - `tripwire.models` — the `Finding` dataclass and severity ordering.
39
+ - `tripwire.config` — workspace-root discovery and the default package registry.
40
+ - `tripwire.ast_helpers` — shared AST/text-matching helpers used across checks.
41
+ - `tripwire.scanner` — file discovery and reading.
42
+ - `tripwire.checks.ast_checks` — checks that walk the parsed AST (won't match
43
+ a dangerous call mentioned in a docstring or string literal).
44
+ - `tripwire.checks.text_checks` — checks that scan raw source lines for
45
+ surface-syntax patterns.
46
+ - `tripwire.checks.manifest_checks` — checks over dependency manifests
47
+ (`pyproject.toml`, `requirements.txt`, etc.), not Python source.
48
+ - `tripwire.reporting` — text/JSON report rendering.
49
+ - `tripwire.cli` — argument parsing and the scan loop.
@@ -0,0 +1,59 @@
1
+ [project]
2
+ name = "boti-tripwire"
3
+ version = "0.1.0"
4
+ description = "Zero-day security scanner for the Boti workspace"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ requires-python = ">=3.13"
8
+ authors = [
9
+ {name = "Luis Valverde", email = "lvalverdeb@gmail.com"},
10
+ ]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Intended Audience :: Developers",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.13",
16
+ "Programming Language :: Python :: 3 :: Only",
17
+ "Operating System :: OS Independent",
18
+ "Topic :: Security",
19
+ ]
20
+ dependencies = [
21
+ "boti>=1.0.0",
22
+ ]
23
+
24
+ [project.scripts]
25
+ tripwire = "tripwire.cli:main"
26
+
27
+ [build-system]
28
+ requires = ["setuptools>=80", "wheel"]
29
+ build-backend = "setuptools.build_meta"
30
+
31
+ [dependency-groups]
32
+ dev = [
33
+ "pytest>=9.0.3",
34
+ "ruff>=0.11.0",
35
+ ]
36
+
37
+ [tool.setuptools]
38
+ include-package-data = true
39
+
40
+ [tool.setuptools.package-dir]
41
+ "" = "src"
42
+
43
+ [tool.setuptools.packages.find]
44
+ where = ["src"]
45
+ include = ["tripwire*"]
46
+
47
+ [tool.setuptools.package-data]
48
+ tripwire = ["py.typed"]
49
+
50
+ [tool.pytest.ini_options]
51
+ testpaths = ["tests"]
52
+
53
+ [tool.ruff]
54
+ line-length = 100
55
+ target-version = "py313"
56
+
57
+ [tool.ruff.lint]
58
+ select = ["E", "F", "W", "I", "UP"]
59
+ ignore = ["E501"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: boti-tripwire
3
+ Version: 0.1.0
4
+ Summary: Zero-day security scanner for the Boti workspace
5
+ Author-email: Luis Valverde <lvalverdeb@gmail.com>
6
+ License-Expression: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Security
14
+ Requires-Python: >=3.13
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: boti>=1.0.0
17
+
18
+ # tripwire
19
+
20
+ Zero-day security scanner for the Boti workspace.
21
+
22
+ Maps every finding to a CWE from the 2025 CWE Top 25, OWASP Top 10:2025, and known
23
+ Python zero-day exploit patterns (pickle bypass CVE-2026-56315, PyYAML shadow
24
+ vulnerability CVE-2026-24009, LangChain SSTI CVE-2025-68664, dependency confusion
25
+ CVE-2025-61774, and more — see the CWE reference printed at the end of every
26
+ text-mode report). 52 checks total: most are AST-based (won't false-positive on a
27
+ dangerous call mentioned in a docstring or comment); the rest are line-regex checks
28
+ for surface-syntax patterns that don't need full parsing.
29
+
30
+ ## Usage
31
+
32
+ ```bash
33
+ uv run tripwire
34
+ uv run tripwire --json > report.json
35
+ uv run tripwire -q
36
+ uv run tripwire --fail-on critical
37
+ uv run tripwire --package my-lib=my-lib/src/my_lib
38
+ ```
39
+
40
+ Exit codes: `0` (no findings at or above `--fail-on`), `1` (one or more).
41
+
42
+ ### Options
43
+
44
+ | Flag | Default | Description |
45
+ | --- | --- | --- |
46
+ | `--json` | off | Machine-readable output |
47
+ | `--quiet` / `-q` | off | Suppress the banner |
48
+ | `--fail-on` | `high` | Severity threshold (`critical`\|`high`\|`medium`\|`low`\|`info`) for the exit code |
49
+ | `--package NAME=PATH` | — | Add or override a scan target package (repeatable) |
50
+
51
+ By default, tripwire scans `boti`, `boti-data`, `boti-dask`, and itself.
52
+
53
+ ## Design
54
+
55
+ - `tripwire.models` — the `Finding` dataclass and severity ordering.
56
+ - `tripwire.config` — workspace-root discovery and the default package registry.
57
+ - `tripwire.ast_helpers` — shared AST/text-matching helpers used across checks.
58
+ - `tripwire.scanner` — file discovery and reading.
59
+ - `tripwire.checks.ast_checks` — checks that walk the parsed AST (won't match
60
+ a dangerous call mentioned in a docstring or string literal).
61
+ - `tripwire.checks.text_checks` — checks that scan raw source lines for
62
+ surface-syntax patterns.
63
+ - `tripwire.checks.manifest_checks` — checks over dependency manifests
64
+ (`pyproject.toml`, `requirements.txt`, etc.), not Python source.
65
+ - `tripwire.reporting` — text/JSON report rendering.
66
+ - `tripwire.cli` — argument parsing and the scan loop.
@@ -0,0 +1,21 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/boti_tripwire.egg-info/PKG-INFO
4
+ src/boti_tripwire.egg-info/SOURCES.txt
5
+ src/boti_tripwire.egg-info/dependency_links.txt
6
+ src/boti_tripwire.egg-info/entry_points.txt
7
+ src/boti_tripwire.egg-info/requires.txt
8
+ src/boti_tripwire.egg-info/top_level.txt
9
+ src/tripwire/__init__.py
10
+ src/tripwire/ast_helpers.py
11
+ src/tripwire/cli.py
12
+ src/tripwire/config.py
13
+ src/tripwire/models.py
14
+ src/tripwire/py.typed
15
+ src/tripwire/reporting.py
16
+ src/tripwire/scanner.py
17
+ src/tripwire/checks/__init__.py
18
+ src/tripwire/checks/ast_checks.py
19
+ src/tripwire/checks/manifest_checks.py
20
+ src/tripwire/checks/text_checks.py
21
+ tests/test_tripwire.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ tripwire = tripwire.cli:main
@@ -0,0 +1 @@
1
+ boti>=1.0.0
@@ -0,0 +1,12 @@
1
+ """Zero-day security scanner for the Boti workspace.
2
+
3
+ Maps findings to the CWE Top 25 (2025), OWASP Top 10:2025, and known Python
4
+ zero-day exploit patterns. See :mod:`tripwire.cli` for the CLI entry point
5
+ and :mod:`tripwire.checks` for the check registry.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from tripwire.cli import main
11
+
12
+ __all__ = ["main"]
@@ -0,0 +1,163 @@
1
+ """AST and text-matching helpers shared by the check functions in
2
+ :mod:`tripwire.checks`.
3
+ """
4
+ from __future__ import annotations
5
+
6
+ import ast
7
+ import re
8
+
9
+ __all__ = [
10
+ "_LOGGING_METHOD_NAMES",
11
+ "_LOG_METHOD_CALL_RE",
12
+ "_LOG_METHOD_CALL_ANY_RE",
13
+ "_LOG_NAME_TOKENS",
14
+ "_NESTED_SCOPE_TYPES",
15
+ "_call_name",
16
+ "_full_attr",
17
+ "_is_re_compile",
18
+ "_is_sqlalchemy_compile",
19
+ "_has_dynamic_arg",
20
+ "_node_line",
21
+ "_has_log_like_token",
22
+ "_walk_skip_nested_scopes",
23
+ "_handler_has_diagnostic",
24
+ "_skip",
25
+ ]
26
+
27
+ # Logging method names shared by every check that needs to recognize a
28
+ # logging call (CWE-778 diagnostic detection, CWE-117 log injection,
29
+ # CWE-532 log secrets). Defined once so these checks can never independently
30
+ # drift out of sync with each other on which method names count as logging.
31
+ _LOGGING_METHOD_NAMES = frozenset(
32
+ {"debug", "info", "warning", "warn", "error", "critical", "exception", "log"}
33
+ )
34
+
35
+ # Derived from _LOGGING_METHOD_NAMES (not a second hand-typed list) — matches
36
+ # a logging call whose argument is an f-string, e.g. `logger.error(f"...")`.
37
+ _LOG_METHOD_CALL_RE = re.compile(
38
+ r'\.(?:' + "|".join(re.escape(name) for name in _LOGGING_METHOD_NAMES) + r')\s*\(\s*f["\']'
39
+ )
40
+
41
+ # Same method-name set, without the f-string requirement — for checks (e.g.
42
+ # check_log_secrets) that need to detect any logging call regardless of the
43
+ # argument's literal form.
44
+ _LOG_METHOD_CALL_ANY_RE = re.compile(
45
+ r'\.(?:' + "|".join(re.escape(name) for name in _LOGGING_METHOD_NAMES) + r')\s*\('
46
+ )
47
+
48
+ # Word-level tokens (not raw substrings) that mark a bare function call as
49
+ # logging-related, e.g. `_log(logger, "debug", ...)` or `log_error(...)`.
50
+ # Matching on whole '.'/'_'-delimited tokens rather than a raw substring test
51
+ # avoids false positives on unrelated names that merely end in "...log" with
52
+ # no delimiter — `catalog.get()`, `dialog.close()`, `backlog.append()`, and
53
+ # `analog_signal.process()` all contain the substring "log" but are not
54
+ # logging calls; none of them tokenize to a standalone "log"-family word.
55
+ _LOG_NAME_TOKENS = frozenset({"log", "logs", "logger", "logging"})
56
+
57
+ # AST node types that introduce a new, separately-executed scope. A statement
58
+ # merely *defined* inside one of these (a nested function/lambda/class body)
59
+ # does not run when the enclosing except block runs, so diagnostics found
60
+ # there don't count as the handler having one.
61
+ _NESTED_SCOPE_TYPES = (ast.FunctionDef, ast.AsyncFunctionDef, ast.Lambda, ast.ClassDef)
62
+
63
+
64
+ def _call_name(node: ast.Call) -> str:
65
+ if isinstance(node.func, ast.Name):
66
+ return node.func.id
67
+ if isinstance(node.func, ast.Attribute):
68
+ return node.func.attr
69
+ return ""
70
+
71
+
72
+ def _full_attr(node: ast.Call) -> str:
73
+ parts: list[str] = []
74
+ cur = node.func
75
+ while isinstance(cur, ast.Attribute):
76
+ parts.append(cur.attr)
77
+ cur = cur.value
78
+ if isinstance(cur, ast.Name):
79
+ parts.append(cur.id)
80
+ parts.reverse()
81
+ return ".".join(parts)
82
+
83
+
84
+ def _is_re_compile(node: ast.Call) -> bool:
85
+ name = _full_attr(node)
86
+ return name in ("re.compile", "re.compile",) or _call_name(node) == "compile" and isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name) and node.func.value.id == "re"
87
+
88
+
89
+ def _is_sqlalchemy_compile(node: ast.Call) -> bool:
90
+ name = _full_attr(node)
91
+ return "compile" in name and any(x in name for x in ("statement", "query", "select", "sql"))
92
+
93
+
94
+ def _has_dynamic_arg(node: ast.Call) -> bool:
95
+ """Check if any positional or keyword argument to a call is dynamic (not a constant)."""
96
+ for arg in node.args:
97
+ if not isinstance(arg, (ast.Constant, ast.Str, ast.Num, ast.NameConstant)):
98
+ return True
99
+ for kw in node.keywords:
100
+ if not isinstance(kw.value, (ast.Constant, ast.Str, ast.Num, ast.NameConstant)):
101
+ return True
102
+ return False
103
+
104
+
105
+ def _node_line(node: ast.AST) -> int:
106
+ return getattr(node, "lineno", 0)
107
+
108
+
109
+ def _has_log_like_token(full_name: str) -> bool:
110
+ """True if any ``.``/``_``-delimited token in *full_name* is a
111
+ logging-related word, e.g. ``"log"`` or ``"logger"`` — not merely present
112
+ as a substring somewhere inside a longer, unrelated word.
113
+ """
114
+ tokens = re.split(r"[._]+", full_name.lower())
115
+ return any(tok in _LOG_NAME_TOKENS for tok in tokens if tok)
116
+
117
+
118
+ def _walk_skip_nested_scopes(node: ast.AST):
119
+ """Like ``ast.walk()``, but does not descend into nested function/lambda/
120
+ class bodies — see ``_NESTED_SCOPE_TYPES`` for why.
121
+
122
+ Checks *node itself* (not just its children) against ``_NESTED_SCOPE_TYPES``
123
+ before recursing, so this is correct both when a scope-creating node is
124
+ reached via recursion from a wrapping statement (e.g. a ``Lambda`` inside
125
+ an ``Assign``) and when it *is* the starting node passed in directly (e.g.
126
+ a top-level ``def`` statement in the handler body being walked itself).
127
+ """
128
+ yield node
129
+ if isinstance(node, _NESTED_SCOPE_TYPES):
130
+ return
131
+ for child in ast.iter_child_nodes(node):
132
+ yield from _walk_skip_nested_scopes(child)
133
+
134
+
135
+ def _handler_has_diagnostic(handler: ast.ExceptHandler) -> bool:
136
+ """True if an ``except`` block logs, re-raises, or otherwise surfaces the
137
+ exception rather than silently swallowing it.
138
+
139
+ Looks for: a call whose attribute name is a logging method (``logger.debug(...)``,
140
+ ``self.logger.error(...)``); a bare function call whose name tokenizes to a
141
+ logging-related word (catches helper wrappers like ``_log(logger, "debug", ...)``
142
+ without false-positiving on unrelated names like ``catalog``/``dialog``); ``warnings.warn(...)``;
143
+ or a ``raise`` statement anywhere in the block (including nested ``if``/``try``,
144
+ but not inside a nested function/lambda/class body — code merely defined there
145
+ doesn't run as part of this handler). Walks the whole subtree, not just
146
+ top-level statements, so a diagnostic inside a nested block still counts.
147
+ """
148
+ for stmt in handler.body:
149
+ for node in _walk_skip_nested_scopes(stmt):
150
+ if isinstance(node, ast.Raise):
151
+ return True
152
+ if not isinstance(node, ast.Call):
153
+ continue
154
+ if isinstance(node.func, ast.Attribute) and node.func.attr in _LOGGING_METHOD_NAMES:
155
+ return True
156
+ full = _full_attr(node)
157
+ if full == "warnings.warn" or _has_log_like_token(full):
158
+ return True
159
+ return False
160
+
161
+
162
+ def _skip(line: str) -> bool:
163
+ return line.strip().startswith("#")
@@ -0,0 +1,124 @@
1
+ """Aggregates every check function into a single ordered CHECKS registry.
2
+
3
+ Each entry is ``(display_name, check_fn)``; ``check_fn`` receives
4
+ ``(path, lines, tree)`` and returns ``list[Finding]``. See
5
+ :mod:`tripwire.checks.ast_checks`, :mod:`tripwire.checks.text_checks`,
6
+ and :mod:`tripwire.checks.manifest_checks` for the implementations.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from tripwire.checks.ast_checks import (
11
+ check_decode_exec_chains,
12
+ check_eval_exec,
13
+ check_except_pass,
14
+ check_format_string,
15
+ check_insecure_default,
16
+ check_insecure_random,
17
+ check_insufficient_logging,
18
+ check_numpy_load,
19
+ check_pandas_eval,
20
+ check_parquet_arrow_deserialize,
21
+ check_request_timeout,
22
+ check_torch_load,
23
+ )
24
+ from tripwire.checks.manifest_checks import (
25
+ check_dependency_cve,
26
+ check_unbounded_pins,
27
+ )
28
+ from tripwire.checks.text_checks import (
29
+ check_arbitrary_write,
30
+ check_assert_security,
31
+ check_command_injection,
32
+ check_crlf,
33
+ check_debug_mode,
34
+ check_exec_driver_sql,
35
+ check_hardcoded_secrets,
36
+ check_hardcoded_tokens,
37
+ check_ldap,
38
+ check_log_injection,
39
+ check_log_secrets,
40
+ check_model_file_load,
41
+ check_null_byte,
42
+ check_numpy_load_lib,
43
+ check_open_redirect,
44
+ check_pandas_pickle,
45
+ check_pandas_xml_xxe,
46
+ check_path_traversal,
47
+ check_pickle,
48
+ check_pth_startup_hooks,
49
+ check_redos,
50
+ check_resource_limits,
51
+ check_sensitive_exposure,
52
+ check_sql_injection,
53
+ check_ssh_host_key,
54
+ check_ssrf,
55
+ check_ssti,
56
+ check_supply_chain,
57
+ check_symlink,
58
+ check_tempfile,
59
+ check_timing_attack,
60
+ check_tls_verify,
61
+ check_trojan_source,
62
+ check_weak_crypto,
63
+ check_weak_hash,
64
+ check_xxe,
65
+ check_yaml_deserialize,
66
+ check_zipslip,
67
+ )
68
+
69
+ __all__ = ["CHECKS"]
70
+
71
+ CHECKS = [
72
+ ("Pickle Deserialization (CWE-502)", check_pickle),
73
+ ("eval/exec/compile Injection (CWE-94)", check_eval_exec),
74
+ ("Command Injection (CWE-78)", check_command_injection),
75
+ ("SQL Injection (CWE-89)", check_sql_injection),
76
+ ("Path Traversal (CWE-22)", check_path_traversal),
77
+ ("Hardcoded Secrets (CWE-798)", check_hardcoded_secrets),
78
+ ("YAML Unsafe Deserialization (CWE-502)", check_yaml_deserialize),
79
+ ("XXE (CWE-611)", check_xxe),
80
+ ("SSRF (CWE-918)", check_ssrf),
81
+ ("Insecure Temp File (CWE-377)", check_tempfile),
82
+ ("Symlink Following (CWE-61)", check_symlink),
83
+ ("ReDoS (CWE-1333)", check_redos),
84
+ ("Assert Security (CWE-617/670)", check_assert_security),
85
+ ("exec_driver_sql Safety (CWE-89)", check_exec_driver_sql),
86
+ ("Supply Chain Dep Confusion (CWE-1104)", check_supply_chain),
87
+ ("Active Debug Code (CWE-489)", check_debug_mode),
88
+ ("Insufficient Logging (CWE-778)", check_insufficient_logging),
89
+ ("Timing Attack (CWE-208)", check_timing_attack),
90
+ ("Sensitive Exposure (CWE-200)", check_sensitive_exposure),
91
+ ("NUL Byte Injection (CWE-158)", check_null_byte),
92
+ ("Resource Limits (CWE-770)", check_resource_limits),
93
+ ("Insecure Random (CWE-338)", check_insecure_random),
94
+ ("SSTI (CWE-1336)", check_ssti),
95
+ ("CRLF Injection (CWE-93)", check_crlf),
96
+ ("LDAP Injection (CWE-90)", check_ldap),
97
+ ("Weak Hash (CWE-328)", check_weak_hash),
98
+ ("Open Redirect (CWE-601)", check_open_redirect),
99
+ ("Log Injection (CWE-117)", check_log_injection),
100
+ ("Format String (CWE-134)", check_format_string),
101
+ ("Arbitrary File Write (CWE-73)", check_arbitrary_write),
102
+ ("Insecure Default (CWE-453)", check_insecure_default),
103
+ ("Log Secrets (CWE-532)", check_log_secrets),
104
+ ("Disabled TLS Verify (CWE-295)", check_tls_verify),
105
+ ("ZipSlip / TarSlip (CWE-22)", check_zipslip),
106
+ ("Hardcoded API Keys (CWE-798)", check_hardcoded_tokens),
107
+ ("Weak Crypto (CWE-327)", check_weak_crypto),
108
+ ("Dependency CVE Scan (CWE-1104)", check_dependency_cve),
109
+ ("Trojan Source (CWE-1007)", check_trojan_source),
110
+ ("HTTP Request Timeout (CWE-1088)", check_request_timeout),
111
+ ("torch.load weights_only (CWE-502)", check_torch_load),
112
+ ("SSH Host Key Verification (CWE-322)", check_ssh_host_key),
113
+ ("except:pass/continue (CWE-391)", check_except_pass),
114
+ ("pandas eval/query Code Injection (CWE-94)", check_pandas_eval),
115
+ ("numpy.load allow_pickle (CWE-502)", check_numpy_load),
116
+ ("pandas.read_pickle (CWE-502)", check_pandas_pickle),
117
+ ("numpy.load library injection (CWE-114)", check_numpy_load_lib),
118
+ ("pandas.read_xml XXE (CWE-611)", check_pandas_xml_xxe),
119
+ (".pth Startup Hooks (CWE-829 / T1546.018)", check_pth_startup_hooks),
120
+ ("Parquet Arrow Deserialization (CWE-502 / CVE-2026-41486)", check_parquet_arrow_deserialize),
121
+ ("Unbounded Dependency Pins (CWE-1104)", check_unbounded_pins),
122
+ ("ML Model File Loading (OWASP ML06 / CWE-502)", check_model_file_load),
123
+ ("Decode-then-Execute Chains (CWE-94)", check_decode_exec_chains),
124
+ ]