@intentsolutionsio/penetration-tester 2.0.0 → 3.0.4
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.
- package/.claude-plugin/plugin.json +8 -3
- package/README.md +8 -0
- package/commands/pentest.md +5 -0
- package/package.json +8 -3
- package/skills/analyzing-tls-config/SKILL.md +221 -0
- package/skills/analyzing-tls-config/references/AUTHORIZATION.md +133 -0
- package/skills/analyzing-tls-config/references/PLAYBOOK.md +267 -0
- package/skills/analyzing-tls-config/references/THEORY.md +128 -0
- package/skills/analyzing-tls-config/scripts/analyze_tls.py +415 -0
- package/skills/auditing-cors-policy/SKILL.md +186 -0
- package/skills/auditing-cors-policy/references/PLAYBOOK.md +220 -0
- package/skills/auditing-cors-policy/references/THEORY.md +142 -0
- package/skills/auditing-cors-policy/scripts/audit_cors.py +350 -0
- package/skills/auditing-npm-dependencies/SKILL.md +254 -0
- package/skills/auditing-npm-dependencies/references/PLAYBOOK.md +175 -0
- package/skills/auditing-npm-dependencies/references/THEORY.md +122 -0
- package/skills/auditing-npm-dependencies/scripts/audit_npm.py +408 -0
- package/skills/auditing-python-dependencies/SKILL.md +251 -0
- package/skills/auditing-python-dependencies/references/PLAYBOOK.md +193 -0
- package/skills/auditing-python-dependencies/references/THEORY.md +122 -0
- package/skills/auditing-python-dependencies/scripts/audit_python.py +459 -0
- package/skills/checking-http-security-headers/SKILL.md +176 -0
- package/skills/checking-http-security-headers/references/PLAYBOOK.md +212 -0
- package/skills/checking-http-security-headers/references/THEORY.md +137 -0
- package/skills/checking-http-security-headers/scripts/check_headers.py +362 -0
- package/skills/checking-license-compliance/SKILL.md +225 -0
- package/skills/checking-license-compliance/references/PLAYBOOK.md +161 -0
- package/skills/checking-license-compliance/references/THEORY.md +152 -0
- package/skills/checking-license-compliance/scripts/check_licenses.py +461 -0
- package/skills/composing-vulnerability-report/SKILL.md +212 -0
- package/skills/composing-vulnerability-report/references/PLAYBOOK.md +180 -0
- package/skills/composing-vulnerability-report/references/THEORY.md +178 -0
- package/skills/composing-vulnerability-report/scripts/compose_report.py +396 -0
- package/skills/confirming-pentest-authorization/SKILL.md +247 -0
- package/skills/confirming-pentest-authorization/references/PLAYBOOK.md +189 -0
- package/skills/confirming-pentest-authorization/references/THEORY.md +167 -0
- package/skills/confirming-pentest-authorization/scripts/check_authorization.py +457 -0
- package/skills/defining-pentest-scope/SKILL.md +227 -0
- package/skills/defining-pentest-scope/references/PLAYBOOK.md +238 -0
- package/skills/defining-pentest-scope/references/THEORY.md +170 -0
- package/skills/defining-pentest-scope/scripts/define_scope.py +472 -0
- package/skills/detecting-command-injection-patterns/SKILL.md +144 -0
- package/skills/detecting-command-injection-patterns/references/PLAYBOOK.md +302 -0
- package/skills/detecting-command-injection-patterns/references/THEORY.md +206 -0
- package/skills/detecting-command-injection-patterns/scripts/scan_cmdi.py +290 -0
- package/skills/detecting-debug-endpoints/SKILL.md +207 -0
- package/skills/detecting-debug-endpoints/references/PLAYBOOK.md +402 -0
- package/skills/detecting-debug-endpoints/references/THEORY.md +218 -0
- package/skills/detecting-debug-endpoints/scripts/probe_debug.py +518 -0
- package/skills/detecting-directory-listing/SKILL.md +206 -0
- package/skills/detecting-directory-listing/references/PLAYBOOK.md +277 -0
- package/skills/detecting-directory-listing/references/THEORY.md +203 -0
- package/skills/detecting-directory-listing/scripts/probe_directory_listing.py +180 -0
- package/skills/detecting-eval-exec-usage/SKILL.md +128 -0
- package/skills/detecting-eval-exec-usage/references/PLAYBOOK.md +306 -0
- package/skills/detecting-eval-exec-usage/references/THEORY.md +159 -0
- package/skills/detecting-eval-exec-usage/scripts/scan_eval.py +223 -0
- package/skills/detecting-exposed-secrets-files/SKILL.md +179 -0
- package/skills/detecting-exposed-secrets-files/references/PLAYBOOK.md +274 -0
- package/skills/detecting-exposed-secrets-files/references/THEORY.md +174 -0
- package/skills/detecting-exposed-secrets-files/scripts/probe_secrets.py +207 -0
- package/skills/detecting-insecure-deserialization/SKILL.md +148 -0
- package/skills/detecting-insecure-deserialization/references/PLAYBOOK.md +333 -0
- package/skills/detecting-insecure-deserialization/references/THEORY.md +199 -0
- package/skills/detecting-insecure-deserialization/scripts/scan_deserialization.py +250 -0
- package/skills/detecting-sql-injection-patterns/SKILL.md +161 -0
- package/skills/detecting-sql-injection-patterns/references/PLAYBOOK.md +317 -0
- package/skills/detecting-sql-injection-patterns/references/THEORY.md +261 -0
- package/skills/detecting-sql-injection-patterns/scripts/scan_sqli.py +354 -0
- package/skills/detecting-ssl-cert-issues/SKILL.md +182 -0
- package/skills/detecting-ssl-cert-issues/references/PLAYBOOK.md +203 -0
- package/skills/detecting-ssl-cert-issues/references/THEORY.md +133 -0
- package/skills/detecting-ssl-cert-issues/scripts/check_cert_chain.py +481 -0
- package/skills/detecting-weak-cryptography/SKILL.md +147 -0
- package/skills/detecting-weak-cryptography/references/PLAYBOOK.md +466 -0
- package/skills/detecting-weak-cryptography/references/THEORY.md +194 -0
- package/skills/detecting-weak-cryptography/scripts/scan_weak_crypto.py +417 -0
- package/skills/fingerprinting-server-software/SKILL.md +191 -0
- package/skills/fingerprinting-server-software/references/PLAYBOOK.md +337 -0
- package/skills/fingerprinting-server-software/references/THEORY.md +183 -0
- package/skills/fingerprinting-server-software/scripts/fingerprint_server.py +347 -0
- package/skills/generating-executive-summary/SKILL.md +261 -0
- package/skills/generating-executive-summary/references/PLAYBOOK.md +201 -0
- package/skills/generating-executive-summary/references/THEORY.md +195 -0
- package/skills/generating-executive-summary/scripts/exec_summary.py +538 -0
- package/skills/mapping-findings-to-owasp-top10/SKILL.md +235 -0
- package/skills/mapping-findings-to-owasp-top10/references/PLAYBOOK.md +193 -0
- package/skills/mapping-findings-to-owasp-top10/references/THEORY.md +160 -0
- package/skills/mapping-findings-to-owasp-top10/scripts/map_owasp.py +540 -0
- package/skills/performing-penetration-testing/SKILL.md +282 -190
- package/skills/performing-penetration-testing/references/OWASP_TOP_10.md +22 -0
- package/skills/performing-penetration-testing/references/REMEDIATION_PLAYBOOK.md +46 -0
- package/skills/performing-penetration-testing/references/SECURITY_HEADERS.md +41 -0
- package/skills/performing-penetration-testing/scripts/code_security_scanner.py +144 -79
- package/skills/performing-penetration-testing/scripts/dependency_auditor.py +116 -93
- package/skills/performing-penetration-testing/scripts/security_scanner.py +574 -446
- package/skills/probing-dangerous-http-methods/SKILL.md +182 -0
- package/skills/probing-dangerous-http-methods/references/PLAYBOOK.md +234 -0
- package/skills/probing-dangerous-http-methods/references/THEORY.md +145 -0
- package/skills/probing-dangerous-http-methods/scripts/probe_methods.py +263 -0
- package/skills/recording-pentest-engagement/SKILL.md +253 -0
- package/skills/recording-pentest-engagement/references/PLAYBOOK.md +203 -0
- package/skills/recording-pentest-engagement/references/THEORY.md +195 -0
- package/skills/recording-pentest-engagement/scripts/record_engagement.py +461 -0
- package/skills/scanning-for-hardcoded-secrets/SKILL.md +215 -0
- package/skills/scanning-for-hardcoded-secrets/references/PLAYBOOK.md +325 -0
- package/skills/scanning-for-hardcoded-secrets/references/THEORY.md +175 -0
- package/skills/scanning-for-hardcoded-secrets/scripts/scan_secrets.py +395 -0
- package/skills/tracing-transitive-vulnerabilities/SKILL.md +235 -0
- package/skills/tracing-transitive-vulnerabilities/references/PLAYBOOK.md +233 -0
- package/skills/tracing-transitive-vulnerabilities/references/THEORY.md +138 -0
- package/skills/tracing-transitive-vulnerabilities/scripts/trace_vulns.py +484 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: auditing-python-dependencies
|
|
3
|
+
description: |
|
|
4
|
+
Audit a Python project's installed dependencies for known CVEs by
|
|
5
|
+
wrapping pip-audit (PyPA's official vulnerability auditor) and
|
|
6
|
+
emitting findings in the canonical penetration-tester schema.
|
|
7
|
+
Detects vulnerable direct AND transitive packages, normalizes
|
|
8
|
+
pip-audit's severity output via OSV severity bands, falls back to
|
|
9
|
+
pip list --outdated when pip-audit isn't installed, and supports
|
|
10
|
+
requirements.txt, pyproject.toml (PEP 621), Pipfile.lock, and
|
|
11
|
+
poetry.lock as input sources.
|
|
12
|
+
Use when: pre-merge gate on a Python project, post-incident sweep
|
|
13
|
+
after a PyPI compromise (e.g. ctx, request-toolbelt typosquats,
|
|
14
|
+
ultralytics 8.3.42 compromise), SOC2 evidence collection, or
|
|
15
|
+
inheriting an unfamiliar Python codebase.
|
|
16
|
+
Threshold: any HIGH or CRITICAL CVE in the resolved dependency
|
|
17
|
+
tree. MODERATE / LOW reported informationally.
|
|
18
|
+
Trigger with: "audit python deps", "pip vulnerability scan",
|
|
19
|
+
"check pypi packages for CVEs", "pip-audit run".
|
|
20
|
+
allowed-tools:
|
|
21
|
+
- Read
|
|
22
|
+
- Bash(pip:*)
|
|
23
|
+
- Bash(pip-audit:*)
|
|
24
|
+
- Bash(python3:*)
|
|
25
|
+
- Glob
|
|
26
|
+
disallowed-tools:
|
|
27
|
+
- Bash(rm:*)
|
|
28
|
+
- Bash(curl:*)
|
|
29
|
+
- Bash(wget:*)
|
|
30
|
+
- Write(.env)
|
|
31
|
+
- Edit(.env)
|
|
32
|
+
- Bash(pip install:*)
|
|
33
|
+
- Bash(pip uninstall:*)
|
|
34
|
+
version: 3.0.0-dev
|
|
35
|
+
author: Jeremy Longshore <jeremy@intentsolutions.io>
|
|
36
|
+
license: MIT
|
|
37
|
+
compatibility: Designed for Claude Code
|
|
38
|
+
tags:
|
|
39
|
+
- security
|
|
40
|
+
- dependency-audit
|
|
41
|
+
- python
|
|
42
|
+
- pypi
|
|
43
|
+
- cve
|
|
44
|
+
- pentest
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
# Auditing Python Dependencies
|
|
48
|
+
|
|
49
|
+
## Overview
|
|
50
|
+
|
|
51
|
+
PyPI hosts north of 500,000 packages, with several thousand new
|
|
52
|
+
releases every day. The package-install model is identical to npm in
|
|
53
|
+
the relevant ways: a `pip install` resolves a transitive graph,
|
|
54
|
+
runs each package's `setup.py` (which executes arbitrary Python at
|
|
55
|
+
install time), and writes the result to your site-packages. The CVE
|
|
56
|
+
attack surface is therefore the same shape: known vulnerabilities,
|
|
57
|
+
maintainer-account takeovers, typosquats, and protestware.
|
|
58
|
+
|
|
59
|
+
The PyPA-blessed auditor is `pip-audit`. It queries the Open Source
|
|
60
|
+
Vulnerabilities (OSV) database (which mirrors PyPA's advisory feed
|
|
61
|
+
plus aggregated CVE / GHSA records) and reports per-package
|
|
62
|
+
vulnerable versions. `pip-audit` integrates with `requirements.txt`,
|
|
63
|
+
`pyproject.toml`, `Pipfile.lock`, and `poetry.lock`, so most Python
|
|
64
|
+
project layouts are first-class.
|
|
65
|
+
|
|
66
|
+
This skill wraps `pip-audit`, normalizes its severity vocabulary to
|
|
67
|
+
the shared `Severity` enum, and emits Findings in the canonical
|
|
68
|
+
penetration-tester schema. If `pip-audit` isn't installed on the
|
|
69
|
+
host, the skill falls back to `pip list --outdated` and emits
|
|
70
|
+
INFO-level findings recommending the operator install pip-audit
|
|
71
|
+
for accurate vulnerability detection.
|
|
72
|
+
|
|
73
|
+
## When the skill produces findings
|
|
74
|
+
|
|
75
|
+
| Finding | Severity | Threshold | Affected control |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| Critical CVE in installed package | **CRITICAL** | OSV severity band corresponds to CVSS ≥ 9.0 | CWE-1104 |
|
|
78
|
+
| High CVE in installed package | **HIGH** | OSV severity band corresponds to CVSS 7.0–8.9 | CWE-1104 |
|
|
79
|
+
| Medium CVE in installed package | **MEDIUM** | OSV severity band corresponds to CVSS 4.0–6.9 | CWE-1104 |
|
|
80
|
+
| Low CVE in installed package | **LOW** | OSV severity band corresponds to CVSS 0.1–3.9 | CWE-1104 |
|
|
81
|
+
| Vulnerable package with no patch | **HIGH** | finding has no `fix_versions` and severity ≥ medium | CWE-1395 |
|
|
82
|
+
| Outdated package (no CVE) | **INFO** | pip list --outdated reports a newer version | (operational) |
|
|
83
|
+
| pip-audit not installed | **INFO** | binary not on PATH; scanner fell back to pip list | (operational) |
|
|
84
|
+
| Audit DB unreachable | **INFO** | pip-audit network error reaching OSV | (operational) |
|
|
85
|
+
|
|
86
|
+
OSV is the upstream of record. pip-audit also consults the PyPA
|
|
87
|
+
advisory database for Python-specific records that may not yet have
|
|
88
|
+
a CVE assigned.
|
|
89
|
+
|
|
90
|
+
## Prerequisites
|
|
91
|
+
|
|
92
|
+
- Python 3.9+
|
|
93
|
+
- `pip-audit` installed (`pip install pip-audit`); skill falls back
|
|
94
|
+
to `pip list --outdated` if absent
|
|
95
|
+
- Target project containing at minimum one of: `requirements.txt`,
|
|
96
|
+
`pyproject.toml`, `Pipfile.lock`, `poetry.lock`
|
|
97
|
+
- Network access to OSV (`api.osv.dev`) and PyPI (`pypi.org`)
|
|
98
|
+
|
|
99
|
+
## Instructions
|
|
100
|
+
|
|
101
|
+
### Step 1 — Identify the scan target
|
|
102
|
+
|
|
103
|
+
Locate the project directory. The scanner auto-detects requirement
|
|
104
|
+
files in order of preference:
|
|
105
|
+
|
|
106
|
+
1. `poetry.lock` (most precise — exact resolved tree)
|
|
107
|
+
2. `Pipfile.lock`
|
|
108
|
+
3. `requirements.txt` (and `requirements-*.txt` siblings)
|
|
109
|
+
4. `pyproject.toml` (PEP 621 dependencies)
|
|
110
|
+
5. Installed environment via `pip list` (last resort)
|
|
111
|
+
|
|
112
|
+
### Step 2 — Run the audit
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python3 ./scripts/audit_python.py /path/to/python-project
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Options:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
Usage: audit_python.py PATH [OPTIONS]
|
|
122
|
+
|
|
123
|
+
Options:
|
|
124
|
+
--output FILE Write findings to FILE (default: stdout)
|
|
125
|
+
--format FMT json | jsonl | markdown (default: markdown)
|
|
126
|
+
--min-severity SEV (default: info)
|
|
127
|
+
--requirement FILE Override auto-detection; specify a particular
|
|
128
|
+
requirements file (repeatable)
|
|
129
|
+
--include-dev Include development dependencies (default: prod
|
|
130
|
+
only when project layout allows the distinction)
|
|
131
|
+
--strict Treat pip-audit warnings as errors
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Step 3 — Interpret findings
|
|
135
|
+
|
|
136
|
+
CRITICAL / HIGH = block release.
|
|
137
|
+
|
|
138
|
+
MEDIUM / LOW = track but don't block; many Python advisories report
|
|
139
|
+
edge-case theoretical issues that don't apply to your usage.
|
|
140
|
+
|
|
141
|
+
INFO = log only; e.g. "outdated but no known CVE" is information for
|
|
142
|
+
your release cadence, not a security action.
|
|
143
|
+
|
|
144
|
+
### Step 4 — Remediation
|
|
145
|
+
|
|
146
|
+
For a vulnerable package with `fix_versions`:
|
|
147
|
+
|
|
148
|
+
1. Bump the version pin in your requirements file:
|
|
149
|
+
|
|
150
|
+
```diff
|
|
151
|
+
- requests==2.20.0
|
|
152
|
+
+ requests==2.31.0
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
2. Run `pip install -r requirements.txt --upgrade` (or
|
|
156
|
+
`poetry lock --no-update && poetry update <pkg>`).
|
|
157
|
+
|
|
158
|
+
3. Run the test suite. CVE fixes occasionally include behavioral
|
|
159
|
+
changes you didn't expect.
|
|
160
|
+
|
|
161
|
+
4. Commit the lock file diff alongside the requirements bump.
|
|
162
|
+
|
|
163
|
+
For a vulnerable transitive dep (one you didn't declare directly):
|
|
164
|
+
|
|
165
|
+
1. Find the parent: `pip show <vulnerable-package>` lists the parents
|
|
166
|
+
in its "Required-by" line.
|
|
167
|
+
|
|
168
|
+
2. Check whether bumping the parent picks up the fix. `pip index
|
|
169
|
+
versions <parent>` lists available versions.
|
|
170
|
+
|
|
171
|
+
3. If parent doesn't have a newer release that floors the vulnerable
|
|
172
|
+
dep above the fix version, pin the transitive dep yourself in
|
|
173
|
+
your requirements file. pip will use the more specific pin.
|
|
174
|
+
|
|
175
|
+
For a vulnerable package with NO fix available:
|
|
176
|
+
|
|
177
|
+
1. Subscribe to PyPA advisory notifications for that package.
|
|
178
|
+
|
|
179
|
+
2. If the vulnerability is exploitable in your usage, either
|
|
180
|
+
replace the package or vendor + patch locally.
|
|
181
|
+
|
|
182
|
+
3. Document the exception in your security register with a
|
|
183
|
+
re-evaluation date.
|
|
184
|
+
|
|
185
|
+
## Examples
|
|
186
|
+
|
|
187
|
+
### Example 1 — Pre-merge gate
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
python3 ./scripts/audit_python.py . --min-severity high --format json --output audit.json
|
|
191
|
+
jq -e '. == []' audit.json || { echo "High/critical Python CVE — fix before merge"; exit 1; }
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Example 2 — CI scan on every push
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
- name: pip-audit
|
|
198
|
+
run: pip install pip-audit
|
|
199
|
+
- name: Run audit
|
|
200
|
+
run: |
|
|
201
|
+
python3 plugins/security/penetration-tester/skills/auditing-python-dependencies/scripts/audit_python.py \
|
|
202
|
+
. --min-severity high --format markdown --output py-audit.md
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Example 3 — SOC2 evidence collection
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
mkdir -p evidence/CC7/
|
|
209
|
+
python3 ./scripts/audit_python.py . --include-dev --format json \
|
|
210
|
+
--output evidence/CC7/py-audit-$(date +%Y%m%d).json
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
`--include-dev` for SOC2: include dev/test deps so auditors see the
|
|
214
|
+
full surface, not just production.
|
|
215
|
+
|
|
216
|
+
## Output
|
|
217
|
+
|
|
218
|
+
JSON / JSONL / Markdown per `lib/report.py`. Exit codes: 0 clean, 1
|
|
219
|
+
high/critical, 2 error.
|
|
220
|
+
|
|
221
|
+
Each Finding includes:
|
|
222
|
+
|
|
223
|
+
- `id` — synthesized as `pypi-audit::<cve-id>` (or `pypi-audit::<ghsa>` / `pypi-audit::<pypa-id>` when no CVE)
|
|
224
|
+
- `severity` — CRITICAL / HIGH / MEDIUM / LOW / INFO
|
|
225
|
+
- `category` — `dependency-vulnerability`
|
|
226
|
+
- `summary` — short CVE / GHSA title
|
|
227
|
+
- `evidence` — affected package, affected version, fix versions, advisory ID
|
|
228
|
+
- `references` — OSV URL, CVE URL, PyPA advisory URL
|
|
229
|
+
|
|
230
|
+
## Error Handling
|
|
231
|
+
|
|
232
|
+
- **pip-audit not installed** → falls back to `pip list --outdated`,
|
|
233
|
+
emits an INFO Finding flagging the degraded scan, and proceeds.
|
|
234
|
+
- **No requirement file found** → emits an INFO Finding "no Python
|
|
235
|
+
project structure recognized" and exits 2.
|
|
236
|
+
- **OSV API unreachable** → emits an INFO Finding documenting the
|
|
237
|
+
outage and exits 0 (no actionable security finding).
|
|
238
|
+
- **pip-audit returns malformed JSON** → emits an INFO Finding with
|
|
239
|
+
the raw output truncated to 500 chars and exits 2.
|
|
240
|
+
|
|
241
|
+
## Resources
|
|
242
|
+
|
|
243
|
+
- `references/THEORY.md` — PyPI supply-chain history, OSV vs NVD vs
|
|
244
|
+
PyPA advisory scopes, why ecosystem-specific severity matters,
|
|
245
|
+
Python-specific install-time risks (setup.py execution, eager
|
|
246
|
+
dependency resolution), pip-audit vs Safety vs Snyk trade-offs
|
|
247
|
+
- `references/PLAYBOOK.md` — Per-toolchain remediation patterns
|
|
248
|
+
(pip + requirements.txt, poetry, pipenv, uv, conda), monorepo /
|
|
249
|
+
workspace scanning, override-equivalent patterns in Python
|
|
250
|
+
ecosystem, GitHub Dependabot ecosystem mapping, SOC2 evidence
|
|
251
|
+
retention
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# PLAYBOOK — Remediating Python Findings
|
|
2
|
+
|
|
3
|
+
## Per-toolchain remediation patterns
|
|
4
|
+
|
|
5
|
+
### Plain requirements.txt + pip
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Edit requirements.txt to bump the pinned version
|
|
9
|
+
sed -i 's/requests==2.20.0/requests==2.31.0/' requirements.txt
|
|
10
|
+
pip install -r requirements.txt --upgrade
|
|
11
|
+
pytest # confirm no behavior regressions
|
|
12
|
+
git add requirements.txt && git commit -m "fix: bump requests to 2.31.0 (CVE-XXXX)"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
If you have a separate `requirements-lock.txt` generated by
|
|
16
|
+
`pip-compile`:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip-compile --upgrade-package requests requirements.in
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Poetry
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
poetry add requests@^2.31.0
|
|
26
|
+
poetry lock --no-update # refresh just the affected entry
|
|
27
|
+
poetry install
|
|
28
|
+
pytest
|
|
29
|
+
git add pyproject.toml poetry.lock
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For a transitive bump (a dep not declared directly):
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
poetry add requests@^2.31.0 --lock # forces resolution even if not direct
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or use the `dependencies` table to pin transitive deps without
|
|
39
|
+
adding them as your project's direct deps.
|
|
40
|
+
|
|
41
|
+
### Pipenv
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pipenv update requests
|
|
45
|
+
pipenv lock
|
|
46
|
+
pipenv install --deploy --ignore-pipfile # smoke test
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### uv (modern fast resolver)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uv pip install --upgrade requests
|
|
53
|
+
uv pip freeze > requirements.txt # if you track frozen requirements
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### conda environments
|
|
57
|
+
|
|
58
|
+
`pip-audit` does not natively audit conda packages, only pip
|
|
59
|
+
packages installed inside a conda environment. If a vulnerability
|
|
60
|
+
affects a conda-installed package, fix via `conda update <pkg>`
|
|
61
|
+
and document the manual remediation; pip-audit will not see the
|
|
62
|
+
finding go away on its own.
|
|
63
|
+
|
|
64
|
+
## Transitive dependency overrides
|
|
65
|
+
|
|
66
|
+
Python has no first-class `overrides` equivalent like npm 8.3+.
|
|
67
|
+
The patterns:
|
|
68
|
+
|
|
69
|
+
### Pin in requirements (works in pip)
|
|
70
|
+
|
|
71
|
+
If `boto3` pulls in `urllib3<2.0` and you need `urllib3>=2.0.2`:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
urllib3>=2.0.2
|
|
75
|
+
boto3==1.34.0
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
pip's resolver prefers the more specific version. This sometimes
|
|
79
|
+
causes conflicts the resolver flags ("ResolutionImpossible"); when
|
|
80
|
+
that happens, the parent itself needs to be bumped.
|
|
81
|
+
|
|
82
|
+
### Poetry constraints
|
|
83
|
+
|
|
84
|
+
```toml
|
|
85
|
+
[tool.poetry.dependencies]
|
|
86
|
+
boto3 = "^1.34.0"
|
|
87
|
+
urllib3 = "^2.0.2" # add as a direct dep to force the floor
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This makes the transitive dep your direct dep, which is messy but
|
|
91
|
+
effective.
|
|
92
|
+
|
|
93
|
+
### Reset and re-resolve
|
|
94
|
+
|
|
95
|
+
When a transitive override produces conflicts, sometimes the cleanest
|
|
96
|
+
fix is to delete the lock file, bump everything, and re-resolve.
|
|
97
|
+
Reserve for major version refreshes or when you have a release window
|
|
98
|
+
to validate the full diff.
|
|
99
|
+
|
|
100
|
+
## Monorepo / workspace scanning
|
|
101
|
+
|
|
102
|
+
For monorepos that have multiple Python projects (often `services/*`
|
|
103
|
+
or `apps/*` layout):
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
for project in services/*/; do
|
|
107
|
+
if [ -f "$project/pyproject.toml" ] || [ -f "$project/requirements.txt" ]; then
|
|
108
|
+
python3 plugins/security/penetration-tester/skills/auditing-python-dependencies/scripts/audit_python.py \
|
|
109
|
+
"$project" --format json --output "audit-$(basename $project).json"
|
|
110
|
+
fi
|
|
111
|
+
done
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The skill scans one project at a time by design — keeps the
|
|
115
|
+
per-project blast radius clear and lets CI parallelize.
|
|
116
|
+
|
|
117
|
+
## GitHub Dependabot ecosystem mapping
|
|
118
|
+
|
|
119
|
+
Dependabot's "pip" ecosystem auto-PRs requirements.txt and
|
|
120
|
+
pyproject.toml bumps. It does NOT audit poetry.lock — for that,
|
|
121
|
+
use the "poetry" ecosystem entry:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
# .github/dependabot.yml
|
|
125
|
+
version: 2
|
|
126
|
+
updates:
|
|
127
|
+
- package-ecosystem: pip
|
|
128
|
+
directory: /
|
|
129
|
+
schedule:
|
|
130
|
+
interval: weekly
|
|
131
|
+
- package-ecosystem: pip # poetry is reported as "pip" too in newer versions
|
|
132
|
+
directory: /services/api
|
|
133
|
+
schedule:
|
|
134
|
+
interval: weekly
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
For uv, Dependabot support was added in 2025; check Dependabot's
|
|
138
|
+
docs for the current ecosystem name.
|
|
139
|
+
|
|
140
|
+
## SOC2 evidence retention
|
|
141
|
+
|
|
142
|
+
For Trust Service Category CC7 (System Operations):
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
mkdir -p evidence/CC7/
|
|
146
|
+
python3 ./scripts/audit_python.py . --include-dev \
|
|
147
|
+
--format json \
|
|
148
|
+
--output evidence/CC7/py-audit-$(date +%Y%m%d).json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Retain at minimum one audit per quarter, plus the audit run that
|
|
152
|
+
preceded each release. Auditors look for evidence that:
|
|
153
|
+
|
|
154
|
+
1. The audit ran on a defined cadence.
|
|
155
|
+
2. Findings were triaged within the window your vuln-response
|
|
156
|
+
policy commits to (typically 7 days for HIGH, 30 days for
|
|
157
|
+
MEDIUM, 90 days for LOW).
|
|
158
|
+
3. Exceptions are documented with re-evaluation dates.
|
|
159
|
+
|
|
160
|
+
## Common false positives
|
|
161
|
+
|
|
162
|
+
Three patterns produce findings that aren't actionable:
|
|
163
|
+
|
|
164
|
+
1. **Dev-only test fixtures pinning old versions** — e.g. tests
|
|
165
|
+
that intentionally exercise an old `requests` to verify backward
|
|
166
|
+
compat. Mark the source file as dev-only via `--include-dev`
|
|
167
|
+
filtering or split test requirements into a separate file.
|
|
168
|
+
|
|
169
|
+
2. **Yanked releases on PyPI** — a release pulled by the maintainer
|
|
170
|
+
may still have an open advisory while no longer installable.
|
|
171
|
+
pip-audit handles yanked correctly in recent versions; older
|
|
172
|
+
versions may still flag.
|
|
173
|
+
|
|
174
|
+
3. **CVEs that don't apply in your usage** — a vulnerability in the
|
|
175
|
+
FTP transport of `urllib3` is irrelevant if you only use HTTPS.
|
|
176
|
+
Don't blanket-suppress; document the per-finding rationale in
|
|
177
|
+
your security register.
|
|
178
|
+
|
|
179
|
+
## When to vendor + patch
|
|
180
|
+
|
|
181
|
+
If a package has an unpatched CRITICAL/HIGH CVE and replacement
|
|
182
|
+
isn't feasible:
|
|
183
|
+
|
|
184
|
+
1. Fork the upstream source into a private vendored copy in your
|
|
185
|
+
repo (e.g. `vendor/<package>/`).
|
|
186
|
+
2. Apply the upstream patch (cherry-pick from the maintainer's PR
|
|
187
|
+
if one exists).
|
|
188
|
+
3. Install from your vendored path: `pip install ./vendor/<package>`.
|
|
189
|
+
4. Set a calendar reminder to re-evaluate quarterly; switch back to
|
|
190
|
+
upstream once a published fix is available.
|
|
191
|
+
|
|
192
|
+
Vendor + patch is a maintenance burden; track it in your security
|
|
193
|
+
register the same way you'd track any other exception.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# THEORY — Why Python Dependency Audits Matter
|
|
2
|
+
|
|
3
|
+
## The Python install model
|
|
4
|
+
|
|
5
|
+
`pip install <package>` does three things in sequence:
|
|
6
|
+
|
|
7
|
+
1. Resolves a transitive dependency graph from PyPI metadata.
|
|
8
|
+
2. Downloads each resolved package as a wheel (`.whl`) or sdist
|
|
9
|
+
(`.tar.gz`).
|
|
10
|
+
3. For sdists, executes the package's `setup.py` (which is arbitrary
|
|
11
|
+
Python) at install time. For wheels, runs any post-install hooks.
|
|
12
|
+
|
|
13
|
+
The `setup.py` execution step is the load-bearing detail. A
|
|
14
|
+
compromised PyPI package can read environment variables, write to
|
|
15
|
+
the user's home directory, exfiltrate data, and pivot to other
|
|
16
|
+
systems — all on `pip install`, before the package is ever imported.
|
|
17
|
+
|
|
18
|
+
## PyPI supply-chain incidents that drove audit adoption
|
|
19
|
+
|
|
20
|
+
| Year | Event | Mechanism |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| 2017 | Typosquat wave (PyTorch, RoboGirl, ...) | Names one character off from popular packages. Some shipped credential-stealing setup.py. |
|
|
23
|
+
| 2022 | `ctx` | Maintainer account compromise. Replaced legitimate package with a credential exfiltrator. ~22k weekly downloads. |
|
|
24
|
+
| 2022 | `request-toolbelt` (typosquat of `requests-toolbelt`) | Same week, same actor, similar tactics. |
|
|
25
|
+
| 2023 | `tornado` typosquats | Multiple variants targeting Tornado web framework users. |
|
|
26
|
+
| 2024 | `ultralytics` 8.3.42 / 8.3.43 | YOLO ML library hijacked through GitHub Actions cache poisoning. Crypto miner in the wheel. |
|
|
27
|
+
| 2025 | `requests-darwin-lite` | Targeted macOS users; trojanized binary inside an otherwise innocent wheel. |
|
|
28
|
+
|
|
29
|
+
Each case relied on either (a) someone installing the malicious
|
|
30
|
+
package by name without checking, or (b) a transitive dep updating
|
|
31
|
+
to a malicious version that an existing project pulled in
|
|
32
|
+
automatically.
|
|
33
|
+
|
|
34
|
+
## OSV, PyPA, and the audit data sources
|
|
35
|
+
|
|
36
|
+
`pip-audit` queries the Open Source Vulnerabilities (OSV) database
|
|
37
|
+
(osv.dev), maintained by Google as an aggregator of ecosystem-specific
|
|
38
|
+
advisory feeds. For Python, OSV ingests the PyPA Advisory Database
|
|
39
|
+
(github.com/pypa/advisory-database), which is the upstream of record
|
|
40
|
+
for Python-specific vulnerabilities.
|
|
41
|
+
|
|
42
|
+
Why OSV and not NVD?
|
|
43
|
+
|
|
44
|
+
- **OSV is ecosystem-aware.** A finding tagged "PyPI" affects exactly
|
|
45
|
+
the packages installed via pip. NVD's CVE list is package-agnostic
|
|
46
|
+
and requires manual mapping to ecosystem.
|
|
47
|
+
- **PyPA records often pre-date CVE assignment.** A vulnerability
|
|
48
|
+
in a Python package can be published in PyPA's database before
|
|
49
|
+
NIST assigns a CVE number. Tools that only query NVD miss the
|
|
50
|
+
early window.
|
|
51
|
+
- **Severity bands are normalized.** OSV maps CVSS scores to a
|
|
52
|
+
consistent severity vocabulary across ecosystems.
|
|
53
|
+
|
|
54
|
+
The skill consumes pip-audit's output (which already does the OSV
|
|
55
|
+
query) rather than querying OSV directly. Reasons: pip-audit's
|
|
56
|
+
parser is mature, handles edge cases (yanked releases, retracted
|
|
57
|
+
advisories), and integrates with PEP 621 / poetry / pipenv project
|
|
58
|
+
layouts natively.
|
|
59
|
+
|
|
60
|
+
## Python-specific install-time risks
|
|
61
|
+
|
|
62
|
+
Two install-time behaviors make Python uniquely vulnerable:
|
|
63
|
+
|
|
64
|
+
### setup.py execution
|
|
65
|
+
|
|
66
|
+
Sdists run `setup.py` to build. `setup.py` is arbitrary Python.
|
|
67
|
+
A malicious sdist can do anything Python can do at install time,
|
|
68
|
+
including:
|
|
69
|
+
|
|
70
|
+
- Read `~/.aws/credentials`, `~/.ssh/id_*`, `.env` files.
|
|
71
|
+
- Open a reverse shell via socket.
|
|
72
|
+
- Modify other installed packages in site-packages.
|
|
73
|
+
|
|
74
|
+
`pip install <package> --only-binary :all:` refuses sdists,
|
|
75
|
+
forcing wheels — but most published packages still publish sdists
|
|
76
|
+
alongside wheels.
|
|
77
|
+
|
|
78
|
+
### Eager dependency resolution
|
|
79
|
+
|
|
80
|
+
Pre-pip 20.3, pip's resolver was first-match-wins, leading to
|
|
81
|
+
inconsistent dependency trees across environments. Pip's modern
|
|
82
|
+
resolver (PEP 517 + 2020-resolver) is consistent but slower; some
|
|
83
|
+
CI pipelines disable it for speed, reintroducing the inconsistency.
|
|
84
|
+
|
|
85
|
+
Inconsistent resolution = the audit on your laptop may show
|
|
86
|
+
different packages than the audit in CI. Locking via `pip-tools`,
|
|
87
|
+
`poetry`, or `uv` is the only durable fix.
|
|
88
|
+
|
|
89
|
+
## pip-audit vs Safety vs Snyk
|
|
90
|
+
|
|
91
|
+
Three audit tools compete in the Python space.
|
|
92
|
+
|
|
93
|
+
| Tool | Backed by | Strengths | Weaknesses |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| pip-audit | PyPA | Official; consumes the PyPA advisory DB directly; supports requirements/poetry/pipenv | Severity normalization is sometimes coarser than CVSS |
|
|
96
|
+
| Safety | safetycli.com | Commercial advisory DB with curated severity; web UI | Free tier rate-limited; relies on a third-party DB |
|
|
97
|
+
| Snyk | Snyk Inc. | Commercial advisory DB; rich vulnerability metadata; web UI | Auth required; commercial pricing for production use |
|
|
98
|
+
|
|
99
|
+
The skill standardizes on pip-audit because it's PyPA-blessed,
|
|
100
|
+
zero-cost, and ships with the data quality SOC2 auditors expect to
|
|
101
|
+
see in evidence packages.
|
|
102
|
+
|
|
103
|
+
## Why severity normalization matters
|
|
104
|
+
|
|
105
|
+
OSV emits severity as free-text strings or CVSS vectors. NVD emits
|
|
106
|
+
CVSS scores. GitHub uses 4 levels. PyPA uses ecosystem-specific
|
|
107
|
+
labels. The penetration-tester `Severity` enum (`lib/finding.py`)
|
|
108
|
+
is the canonical mapping target so downstream consumers (executive
|
|
109
|
+
reports, SOC2 evidence collection, dashboards) see one vocabulary
|
|
110
|
+
across every tool.
|
|
111
|
+
|
|
112
|
+
## When "no fix" is itself a finding
|
|
113
|
+
|
|
114
|
+
A vulnerability with no `fix_versions` is not less severe — it's
|
|
115
|
+
MORE remediation-bound. You can't `pip install -U` your way out of
|
|
116
|
+
it. The skill bumps such findings to at-least HIGH severity to make
|
|
117
|
+
this visible in the report. Operator options are limited:
|
|
118
|
+
|
|
119
|
+
1. Pin to an older safe version (if one exists pre-vulnerability).
|
|
120
|
+
2. Vendor the package locally and patch it in-tree.
|
|
121
|
+
3. Replace the package with an alternative.
|
|
122
|
+
4. Accept the risk with an explicit security-register exception.
|