| Audit registry unreachable |
INFO |
npm exits non-zero with network error
Audit a Python project's installed dependencies for known CVEs by wrapping pip-audit (PyPA's official vulnerability auditor) and emitting findings in the canonical penetration-tester schema.
ReadBash(pip:*)Bash(pip-audit:*)Bash(python3:*)Glob
Auditing Python Dependencies
Overview
PyPI hosts north of 500,000 packages, with several thousand new
releases every day. The package-install model is identical to npm in
the relevant ways: a pip install resolves a transitive graph,
runs each package's setup.py (which executes arbitrary Python at
install time), and writes the result to your site-packages. The CVE
attack surface is therefore the same shape: known vulnerabilities,
maintainer-account takeovers, typosquats, and protestware.
The PyPA-blessed auditor is pip-audit. It queries the Open Source
Vulnerabilities (OSV) database (which mirrors PyPA's advisory feed
plus aggregated CVE / GHSA records) and reports per-package
vulnerable versions. pip-audit integrates with requirements.txt,
pyproject.toml, Pipfile.lock, and poetry.lock, so most Python
project layouts are first-class.
This skill wraps pip-audit, normalizes its severity vocabulary to
the shared Severity enum, and emits Findings in the canonical
penetration-tester schema. If pip-audit isn't installed on the
host, the skill falls back to pip list --outdated and emits
INFO-level findings recommending the operator install pip-audit
for accurate vulnerability detection.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Critical CVE in installed package |
CRITICAL |
OSV severity band corresponds to CVSS ≥ 9.0 |
CWE-1104 |
| High CVE in installed package |
HIGH |
OSV severity band corresponds to CVSS 7.0–8.9 |
CWE-1104 |
| Medium CVE in installed package |
MEDIUM |
OSV severity band corresponds to CVSS 4.0–6.9 |
CWE-1104 |
| Low CVE in installed package |
LOW |
OSV severity band corresponds to CVSS 0.1–3.9 |
CWE-1104 |
| Vulnerable package with no patch |
HIGH |
finding has no fix_versions and severity ≥ medium |
CWE-1395 |
| Outdated package (no CVE) |
INFO |
pip list --outdated reports a newer version |
(operational) |
| pip-audit not installed |
INFO |
binary not on PATH; scanner fell back to pip list |
(operational) |
| Audit DB unreachable |
INFO |
pip-audit network error reaching OSV |
(operational) |
OSV is the upstream of record. pip-audit also consults the PyPA<
Audit a target's HTTP security headers — CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and the Cross-Origin trio (COOP, COEP, CORP).
ReadBash(python3:*)Bash(curl:*)
Checking HTTP Security Headers
Overview
HTTP response headers are the cheapest defense-in-depth layer most web
apps ship. Each header closes one specific attack class — HSTS forces
HTTPS, CSP blocks script injection, X-Frame-Options blocks clickjacking,
etc. Missing headers don't break the app; they just leave the attack
class open. This skill probes for the presence + value correctness of
the canonical security-relevant headers.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| HSTS header missing |
HIGH |
No Strict-Transport-Security on HTTPS response |
OWASP A05:2021 |
| HSTS max-age below preload threshold |
MEDIUM |
max-age under 31536000s (1y) |
hstspreload.org |
| HSTS includeSubDomains missing for preload |
LOW |
preload directive without includeSubDomains |
hstspreload.org |
| CSP header missing |
HIGH |
No Content-Security-Policy header |
OWASP A03:2021 |
| CSP allows unsafe-inline |
MEDIUM |
script-src or style-src includes 'unsafe-inline' |
OWASP A03:2021 |
| CSP allows unsafe-eval |
MEDIUM |
script-src includes 'unsafe-eval' |
OWASP A03:2021 |
| CSP frame-ancestors AND X-Frame-Options both missing |
HIGH |
Clickjacking open |
CWE-1021 |
| X-Content-Type-Options:nosniff missing |
MEDIUM |
MIME-sniff attack open |
OWASP A05:2021 |
| Referrer-Policy missing or unsafe-url |
MEDIUM |
Cross-origin URL leakage |
OWASP A05:2021 |
| Permissions-Policy missing |
LOW |
Camera/mic/geo permissions unrestricted |
Permissions Policy spec |
| Server: header discloses version |
LOW |
nginx/1.18.0 → fingerprintable |
CWE-200 |
| Cache-Control public on authenticated response |
HIGH |
Shared cache may serve user A's response to user B |
CWE-525 |
Prerequisites
- Python 3.9+
- Authorization for non-local targets
Instructions
Step 1 — Confirm authorization
"Do you have authorization to perform header testing on this target?
I need confirmation before proceeding."
Step 2 — Run the scanner
python3 ${CLAUDE_PLUGIN_ROOT}/skills/checking-http-security-headers/scripts/check_headers.py \
https
Audit a project's dependency licenses against an explicit policy (allow-list / deny-list / review-required) and flag incompatibilities before they ship to production.
ReadBash(python3:*)Bash(pip:*)Bash(npm:*)Glob
Checking License Compliance
Overview
License compliance is a security concern only in the indirect sense
that an unintended license obligation can force you to release
proprietary source code, retroactively invalidate a customer
contract, or render an M&A transaction infeasible. The cost is
legal and contractual rather than exploitative — but the
consequence ladder is real.
The most-stepped-on landmine is copyleft contamination:
unintentionally including a GPL or AGPL-licensed package in a
codebase the rest of which is permissively licensed (MIT, Apache-2.0,
BSD). The terms of the GPL family say that any project distributing
GPL code MUST itself release source under a GPL-compatible license.
If your package.json says MIT and one of your transitive deps is
GPL-2.0, you may be obligated to either re-license your code or
remove the dep.
This skill audits the resolved dependency tree against an explicit
policy file and emits findings for:
- Direct deps with deny-listed licenses
- Transitive deps with deny-listed licenses
- Packages with UNKNOWN license metadata (no SPDX identifier)
- License conflicts between metadata and source headers
- Combinations of licenses that are mutually incompatible (e.g.
GPL-2.0 + Apache-2.0 without a patent grant)
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Strong-copyleft in permissive project |
CRITICAL |
GPL-2.0/3.0, AGPL-3.0, or similar in a project declaring MIT/Apache-2.0/BSD |
(legal) |
| Weak-copyleft requiring source disclosure |
HIGH |
LGPL family in a project where the obligation isn't being met (no source-availability commitment) |
(legal) |
| Custom / non-SPDX license |
HIGH |
License field doesn't match SPDX expression syntax; requires legal review |
(legal) |
| Unknown license |
MEDIUM |
Package has no license field, no LICENSE file detected |
(legal) |
| Deny-listed license (per policy) |
HIGH |
Package license is in the explicit deny-list in the policy file |
(legal) |
| Review-required license (per policy) |
MEDIUM |
Package license is in the review-list (e.g. MPL-2.0) |
(legal) |
| Incompatible license combination |
HIGH |
Detected pair of licenses known to conflict (e.g. GPL-2.0-only + Apache-2.0) |
(legal) |
| License declared differently in metadata vs source headers |
Read findings JSONL files from cluster 1-4 skills, deduplicate by fingerprint, group by severity, and compose a deliverable- grade markdown vulnerability report with per-finding sections (title, severity, target, detail, remediation, evidence) and a top-level summary table.
ReadWriteBash(python3:*)Glob
Composing Vulnerability Report
Overview
After cluster 1-4 scan skills run, each one produces a Findings
file. A typical engagement ends up with eight to twenty such files
across the different skill categories. The customer wants ONE
vulnerability report — comprehensive, deduplicated, organized by
severity, with each finding cross-referenced to its source skill
and target.
This skill consumes one or more findings files (JSONL preferred,
JSON list also accepted), deduplicates entries by the canonical
fingerprint defined in lib/finding.py, enriches each finding
with a CVSS v3.1 vector when one isn't present (using a deterministic
heuristic based on severity + category — explicitly noted as
"derived, not assigned by NVD" in the output), and emits a single
markdown report with per-finding sections plus a top-level
summary table.
The report has a defined structure that downstream tools (next
two skills in cluster 6) consume:
- Header — engagement ID, generation timestamp, source files
- Summary table — finding count by severity
- Per-severity sections — CRITICAL first, then HIGH, MEDIUM,
LOW, INFO
- Per-finding subsections — title, severity, target, detail,
remediation, evidence, references
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Source file unparseable |
HIGH |
JSON/JSONL parse fails |
(operational) |
| Finding missing required field |
HIGH |
A finding record is missing title, severity, target, detail, or remediation |
(operational) |
| Duplicate fingerprint across files |
INFO |
Same finding appears in N>1 sources; reported as deduplication count |
(informational) |
| Source file has zero findings |
INFO |
Empty or all-info-only file; reported but not an error |
(informational) |
| Report generated cleanly |
INFO |
Positive confirmation |
(informational) |
Prerequisites
- Python 3.9+
- One or more findings files in JSON or JSONL format produced by
any cluster 1-4 scan skill (which all share lib/finding.py
schema)
Instructions
Step 1 — Gather findings sources
By default the skill reads every file matching
engagement/findings/.json and engagement/findings/.jsonl.
Override with --source FILE (repeatable).
Step 2 — Run the composer<
Verify that a penetration test has explicit, written, signed authorization before any scanning begins.
ReadBash(python3:*)Glob
Confirming Pentest Authorization
Overview
Penetration testing is computer access. Without explicit
authorization from the owner of the system under test, that
access is a crime — Computer Fraud and Abuse Act in the US,
Computer Misuse Act in the UK, equivalent laws everywhere
else. The line between an authorized pentester and an
unauthorized attacker is one signature on one document.
The penetration-tester pack's other skills (TLS analysis, CORS
audit, dependency CVE scan, etc.) all assume that line has been
crossed correctly. This skill is the first gate the orchestrator
routes to. It refuses to declare an engagement authorized until
a Rules of Engagement (ROE) attestation file exists, is signed,
and contains the fields any real-world legal review will look for.
This is not paranoia or paperwork theater. Engagements DO go
sideways: scope creeps mid-test, a tester probes an out-of-scope
adjacent system, an SOC team escalates a "real" attack to legal,
and the question "show us the ROE" comes up. If the ROE is in
order, the answer is "here it is." If not, the conversation gets
expensive fast.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| ROE file missing |
CRITICAL |
No attestation file at the expected path |
(legal) |
| Required field missing |
CRITICAL |
authorizer, inscopetargets, timewindow, emergencycontact, or signature absent |
(legal) |
| Signature missing |
CRITICAL |
No signature_block in ROE |
(legal) |
| Signer not in allowlist |
CRITICAL |
signer email/key id not in .allowed-authorizers |
(legal) |
| Time window expired |
HIGH |
current time outside timewindow.start / timewindow.end |
(legal) |
| Time window not yet active |
HIGH |
current time before time_window.start |
(legal) |
| In-scope target list empty |
HIGH |
inscopetargets field present but empty |
(legal) |
| Out-of-scope override (manual flag) |
MEDIUM |
tester requests a target not in the in-scope list |
(legal) |
| Stale ROE (>30 days from sign date) |
MEDIUM |
lastsignedat older than 30 days; suggests refresh |
(operational) |
| ROE present + signed + in window |
INFO |
All gates pass; engage
Parse the ROE scope definition, enumerate every in-scope target (hostnames, IPs, CIDRs, URLs, cloud accounts, SaaS tenants), validate syntax, detect overlap with out-of-scope or known third-party SaaS ranges, and emit a normalized target list plus IP allowlist for scanning tools.
ReadBash(python3:*)Glob
Defining Pentest Scope
Overview
A pentest scope is a list of permission boundaries. Get it wrong
and you either (a) miss real exposure by failing to test something
the customer expected covered, or (b) probe something you weren't
allowed to touch and turn the engagement into a liability event.
Both failure modes share a root cause: the scope list was a vague
narrative ("test the marketing site and the API") rather than a
machine-readable, syntactically-validated, conflict-checked
artifact.
This skill takes the in-scope and out-of-scope sections from a ROE
and produces three deliverables:
- Normalized target list — every entry parsed into a
structured form (host vs CIDR vs URL path vs cloud account vs
SaaS tenant), with explicit type tagging. Downstream cluster
1-4 skills consume this list rather than raw strings.
- IP allowlist — flat list of IPv4 and IPv6 addresses /
CIDRs ready to paste into scanner configurations (nmap target
list, Burp scope file, AWS WAF allowlist, etc.).
- Conflict report — Findings flagging syntactically-malformed
entries, overlap between in-scope and out-of-scope, inclusion
of reserved ranges (RFC1918, link-local, multicast), and known
third-party SaaS infrastructure that needs separate authz.
The skill does NOT perform DNS resolution or network probing —
that would itself be a "first probe" of the target, which by the
governance model must happen AFTER scope is locked.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Malformed target syntax |
HIGH |
Entry doesn't parse as host / CIDR / URL / account-id |
(legal) |
| In-scope overlaps out-of-scope |
CRITICAL |
An in-scope target falls within an out-of-scope CIDR |
(legal) |
| Reserved range without acknowledgement |
HIGH |
RFC1918, link-local (169.254/16), multicast (224/4), broadcast in in-scope list |
(operational) |
| Known third-party SaaS in scope |
HIGH |
In-scope IP matches a known SaaS range (AWS, Cloudflare, GitHub, etc.) without separate authz |
(legal) |
| Duplicate target |
INFO |
Same target appears multiple times |
(operational) |
Wildcard subdomain (e.g. *.acme.example) |
INFO |
Wildcards expand at scan time |
(informational) |
| All targets validated cleanly |
INFO |
Positive confirmation |
(informatio
Scan a source tree for command-injection vulnerable patterns: shell=True calls in Python subprocess, os.
ReadBash(python3:*)GlobGrep
Detecting Command Injection Patterns
Overview
Command injection (CWE-78, OWASP A03:2021) shows up wherever an
application shells out to a binary. Image conversion (convert),
archive extraction (tar, unzip), video processing (ffmpeg),
DNS lookup (dig), and "we just need to call this CLI tool once"
are the common origins.
The vulnerability shape is universal: a string is built including
user input, then handed to a shell interpreter. The shell parses
the string with normal shell semantics — including ;, |, &,
$(), backticks. Any of those in the user-controlled portion
becomes shell-executable.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
Python subprocess.run(..., shell=True) with interpolation |
CRITICAL |
f-string / concat / format argument with shell=True |
CWE-78 |
Python os.system(...) with interpolation |
CRITICAL |
non-literal argument |
CWE-78 |
Python os.popen(...) with interpolation |
CRITICAL |
non-literal argument |
CWE-78 |
Node child_process.exec(...) with template literal |
CRITICAL |
${...} in the command string |
CWE-78 |
Node child_process.execSync(...) with template |
CRITICAL |
same |
CWE-78 |
| Ruby backticks with interpolation |
CRITICAL |
` cmd #{var} ` |
CWE-78 |
Ruby Kernel#system(string) with interpolation |
CRITICAL |
system("cmd #{var}") |
CWE-78 |
Go exec.Command("sh", "-c", ...) with interpolation |
HIGH |
shell wrapper with var |
CWE-78 |
PHP system / exec / passthru / shell_exec with $-interp |
CRITICAL |
system("cmd $var") |
CWE-78 |
Java Runtime.exec(String) with concat |
HIGH |
single-string form (vs array) with var |
CWE-78 |
Prerequisites
- Python 3.9+
- Target source tree on local filesystem
Instructions
Step 1 — Run the scanner
python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-command-injection-patterns/scripts/scan_cmdi.py /path/to/repo
Options:
Probe a target for accidentally-public admin / debug / introspection endpoints — Spring Boot Actuator, Apache server-status, Prometheus metrics, GraphQL playground, Swagger UI, phpMyAdmin, JMX-over-HTTP (Jolokia), Elasticsearch _cat, Kibana / Grafana / Eureka / Consul panels.
ReadBash(python3:*)Bash(curl:*)
Detecting Debug Endpoints
Overview
Modern web stacks ship rich introspection by default. Spring Boot
Actuator exposes /actuator/env (every environment variable),
/actuator/heapdump (a live heap snapshot that contains credentials),
/actuator/jolokia (JMX bean invocation = pre-auth RCE in some
configurations). Apache mod_status exposes /server-status with
internal IPs, request counts, and the URL of every active request.
Prometheus /metrics exposes operational telemetry that often
includes connection-string-bearing labels by accident. phpMyAdmin
exposes the entire database if unauthenticated.
These are not bugs in the frameworks. They're features that ship
enabled-by-default for development convenience and stay enabled in
production because nobody disabled them at install time. The probe
set covers the canonical 40+ paths and grades each by the response
fingerprint specific to that framework.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
Spring Boot Actuator /env exposed |
CRITICAL |
200 + body has "propertySources" |
OWASP A05:2021 |
Spring Boot Actuator /heapdump exposed |
CRITICAL |
200 + Content-Type: application/octet-stream + multi-MB body |
CWE-200 |
Spring Boot Actuator /jolokia exposed |
CRITICAL |
200 + body has "agent":"jolokia" |
CWE-749 |
| phpMyAdmin reachable |
CRITICAL |
200 + HTML body contains "phpMyAdmin" + login form |
OWASP A07:2021 |
Prometheus /metrics exposed |
HIGH |
200 + body has # HELP or # TYPE lines |
CWE-200 |
Apache mod_status exposed |
HIGH |
200 + body contains "Apache Server Status" |
CWE-200 |
Spring Boot Actuator /actuator index |
HIGH |
200 + body has "_links" JSON |
OWASP A05:2021 |
Generic /admin returning 200 (not 401/403) |
HIGH |
200 + HTML body with admin-shaped UI |
CWE-285 |
Elasticsearch _cat exposed |
HIGH |
200 + body matches health\s+status\s+index |
CWE-200 |
| GraphQL Playground on prod |
MEDIUM |
200 + body contains "GraphQLPlayground" |
CWE-200 |
<
Probe a target for directories that return auto-generated index listings instead of denying or serving a specific file — exposes the full file tree under any reachable directory, including files the application never linked to.
ReadBash(python3:*)Bash(curl:*)
Detecting Directory Listing
Overview
Web servers can be configured to auto-generate an HTML index page
when a request hits a directory without a matching default file
(no index.html / index.php / etc.). The auto-generated page
lists every file in the directory. This is by design for static-
file servers and FTP-style file-sharing setups; it's a misconfiguration
on application servers where the file tree was never meant to be
public.
The risk compounds in two ways:
- File enumeration without prior knowledge. Attackers find files
you didn't link to (backup files, log files, old uploads).
- Chaining with exposed-files (#6). A
/.git/ request that
returns an autoindex listing reveals every object file under
.git/objects/ and confirms the entire repo is reachable for
GitDumper-style reconstruction.
This skill probes commonly-vulnerable directory paths and grades
each based on the framework-specific autoindex fingerprint.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Application-root directory listing |
HIGH |
/ returns autoindex page |
OWASP A05:2021 |
| Backup / upload / log directory listing |
HIGH |
/backup/, /uploads/, /logs/, /dump/ autoindex |
CWE-548 |
Asset directory listing (/assets/, /static/) |
MEDIUM |
autoindex on asset dirs (enables file enumeration) |
CWE-548 |
| Config directory listing |
CRITICAL |
/config/, /conf/, /.config/ autoindex |
NIST 800-53 SC-28 |
| VCS subdir listing (chains with skill #6) |
CRITICAL |
/.git/, /.svn/, /.hg/ autoindex |
NIST 800-53 SC-28 |
| Generic root reachable via autoindex |
MEDIUM |
/ or arbitrary path autoindex on app server |
OWASP A05:2021 |
Prerequisites
- Python 3.9+ with
requests
- Authorization for non-local targets
Instructions
Step 1 — Confirm Authorization
"Do you have authorization to perform directory-listing discovery on
this target? I need confirmation before proceeding."
Step 2 — Run the scanner
python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-directory-listing/scripts/pro
Scan a source tree for dynamic-code-execution APIs that an attacker can hijack: Python eval / exec / compile, JavaScript eval / Function() / setTimeout(string), Ruby eval / instance_eval / class_eval, Java ScriptEngine, PHP eval / assert($str), .
ReadBash(python3:*)GlobGrep
Detecting eval / exec Usage
Overview
Dynamic-code-execution APIs (CWE-95 Eval Injection) let an
application interpret a string as code at runtime. If the string
contains anything user-controllable, the application has handed
the attacker arbitrary code execution.
The defensive posture: don't use these APIs. The exceptions are
narrow: rule engines, formula evaluators (spreadsheet = formulas),
plugin systems with explicit sandboxing. For everything else,
there's almost always a safer alternative.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
Python eval(...) with non-literal |
CRITICAL |
argument contains var ref |
CWE-95 |
Python exec(...) with non-literal |
CRITICAL |
argument contains var ref |
CWE-95 |
Python compile(...) with non-literal |
HIGH |
source string contains var |
CWE-95 |
Python import(var) |
HIGH |
dynamic module loading |
CWE-95 |
JS eval(...) |
CRITICAL |
any |
CWE-95 |
JS new Function(str) |
CRITICAL |
any non-literal |
CWE-95 |
JS setTimeout/setInterval(string) |
HIGH |
string instead of function |
CWE-95 |
Ruby eval(...)/instanceeval(...)/classeval(...) |
CRITICAL |
non-literal |
CWE-95 |
PHP eval(...) |
CRITICAL |
always |
CWE-95 |
PHP assert($str) |
CRITICAL |
(legacy code-eval form) |
CWE-95 |
PHP create_function |
CRITICAL |
deprecated, eval-equivalent |
CWE-95 |
Java ScriptEngineManager + eval |
HIGH |
dynamic script execution |
CWE-95 |
C# Activator.CreateInstance(Type.GetType(str)) |
HIGH |
type loading from string |
CWE-95 |
Prerequisites
- Python 3.9+
- Source tree on local filesystem
Instructions
Run
python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-eval-exec-usage/scripts/scan_eval.py /path/to/repo
Options: --output FILE, --format json|jsonl|markdown
Probe a target for accidentally-served secret-bearing files in the web root — `.
ReadBash(python3:*)Bash(curl:*)
Detecting Exposed Secrets Files
Overview
The single highest-value pentest probe per HTTP request. A .git/config
disclosure leaks repo URL + credentials embedded in remote URLs. A .env
disclosure leaks every API key the app has. A backup.sql disclosure
leaks the entire database. These are not "weak crypto" findings that need
a chained exploit. They are direct, immediate compromise.
The probe set is the canonical 40+ paths web servers commonly expose by
accident: VCS directories (.git/, .svn/, .hg/), dotenv files,
OS metadata (.DS_Store), database dumps, archive files, IDE configs,
CI configs, and key files. Each is fingerprinted to distinguish a true
positive (server returns the file's expected content) from a 200 OK
that's actually the application's SPA index page catching the route.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
.git/HEAD reachable + valid content |
CRITICAL |
200 + body matches ref: or 40-char SHA |
NIST 800-53 SC-28 |
.git/config reachable + repo URL leaked |
CRITICAL |
200 + body matches [remote |
NIST 800-53 SC-28 |
.env reachable + dotenv format |
CRITICAL |
200 + body matches KEY=VALUE lines |
OWASP A05:2021 |
.sql / .dump / backup.* reachable |
CRITICAL |
200 + body looks like SQL or binary dump |
CWE-538 |
.aws/credentials reachable |
CRITICAL |
200 + body matches [default]\nawsaccesskey_id |
CWE-200 |
id_rsa / .pem / .key reachable |
CRITICAL |
200 + body matches BEGIN PRIVATE KEY or BEGIN RSA |
CWE-321 |
.svn/entries / .hg/store/ reachable |
HIGH |
200 + body matches VCS format |
NIST 800-53 SC-28 |
.DS_Store reachable |
MEDIUM |
200 + binary blob with Bud1 magic |
CWE-538 |
IDE configs (.idea/, .vscode/) reachable |
LOW |
200 + JSON/XML |
CWE-200 |
composer.json / package.json reachable on prod |
LOW |
200 + valid JSON in non-API root |
CWE-200 |
Scan a source tree for unsafe-by-default deserialization APIs: Python pickle.
ReadBash(python3:*)GlobGrep
Detecting Insecure Deserialization
Overview
Insecure deserialization (CWE-502, OWASP A08:2021) is the highest-
severity injection class in many language stacks because it directly
maps to RCE. Pickle, Java serialization, PHP unserialize, and
BinaryFormatter all execute object-construction code during
deserialization. If that code includes reduce /
readObject / __wakeup / OnDeserialization callbacks that
the attacker controls, the deserialization step IS code execution.
Most legitimate use cases have safer alternatives (JSON for data,
YAML with safe-load, Protocol Buffers, Avro). The remaining cases
need explicit type allow-lists and HMAC-signed payloads.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
Python pickle.loads(...) |
CRITICAL |
always (untrusted input) |
CWE-502 |
Python pickle.load(file) |
CRITICAL |
always |
CWE-502 |
Python dill.loads |
CRITICAL |
always |
CWE-502 |
Python yaml.load(...) without Loader= |
CRITICAL |
unsafe legacy default |
CWE-502 |
Python yaml.unsafe_load(...) |
CRITICAL |
explicit unsafe |
CWE-502 |
Python shelve.open(...) |
HIGH |
pickle-backed; user-controllable filename |
CWE-502 |
Java ObjectInputStream.readObject() |
CRITICAL |
always |
CWE-502 |
PHP unserialize($input) |
CRITICAL |
non-literal input |
CWE-502 |
.NET BinaryFormatter.Deserialize(...) |
CRITICAL |
deprecated unsafe API |
CWE-502 |
.NET NetDataContractSerializer |
CRITICAL |
also unsafe |
CWE-502 |
.NET LosFormatter.Deserialize |
CRITICAL |
ViewState path |
CWE-502 |
Ruby Marshal.load(...) |
CRITICAL |
non-literal |
CWE-502 |
Ruby YAML.load(...) (pre-3.1 Psych) |
CRITICAL |
safe in Psych 4.0+; needs version check |
CWE-502 |
Node.js node-serialize.unserialize |
CRITICAL |
known-vulnerable lib |
CWE-502 |
Node.js seria
Scan a source tree for SQL-injection vulnerable patterns: string concatenation into queries, f-string interpolation in SQL, string-format substitution into raw queries, deprecated cursor methods (cursor.
ReadBash(python3:*)GlobGrep
Detecting SQL Injection Patterns
Overview
SQL injection (CWE-89, OWASP A03:2021) remains one of the highest-
impact and most-easily-introduced vulnerability classes. The fix is
near-universal: use parameterized queries. The cause when introduced:
an engineer concatenates user input into a SQL string because the
ORM's parameterization mechanism wasn't obvious, or because they
"just need to add a quick condition."
The scanner reads source files and grades each apparent SQL-string
construction against the threshold table.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| f-string with SQL keywords + user input |
CRITICAL |
f"SELECT * FROM users WHERE id = {user_id}" |
CWE-89 |
| String concat into SQL keyword string |
CRITICAL |
"SELECT ... " + var + " ..." |
CWE-89 |
| %-format SQL string |
HIGH |
"SELECT * FROM %s" % table_name |
CWE-89 |
.format() into SQL string |
HIGH |
"SELECT {} FROM users".format(col) |
CWE-89 |
cursor.execute(f"...") |
CRITICAL |
f-string passed directly to cursor.execute |
CWE-89 |
sequelize.query with template literal |
HIGH |
sequelize.query(\SELECT * FROM ${table}\) |
CWE-89 |
| Knex / sequelize raw() with interpolation |
HIGH |
knex.raw('SELECT * FROM ' + table) |
CWE-89 |
Django .extra() with raw SQL |
MEDIUM |
Model.objects.extra(where=['col = ' + val]) |
CWE-89 |
cursor.executemany with string-built query |
CRITICAL |
Same risk as execute |
CWE-89 |
JDBC Statement.execute with concat |
HIGH |
Java pattern: not PreparedStatement |
CWE-89 |
Rails where() with string interpolation |
HIGH |
User.where("name = '#{name}'") |
CWE-89 |
Go db.Query with fmt.Sprintf |
HIGH |
db.Query(fmt.Sprintf("...", arg)) |
CWE-89 |
Prerequisites
- Python 3.9+
- Target source tree on local filesystem
Instructions
Step 1 — Run the scanner
python3 ${CLAUDE_PLUGIN_ROOT
Audit a target's TLS certificate beyond protocol/expiry — chain ordering, OCSP stapling, revocation status, Certificate Transparency presence, key-usage flags, and over-broad wildcards.
ReadBash(python3:*)Bash(openssl:*)
Detecting SSL Certificate Issues
Overview
This skill is the second-level cert audit, run after analyzing-tls-config
clears the protocol+cipher+expiry+hostname basics. It surfaces issues
that don't break the handshake today but make the cert fragile or open
to soft-bypass attacks: missing OCSP stapling forces clients to phone
home to the CA (privacy + latency hit), missing Certificate Transparency
SCTs are rejected by Chrome since 2018, an out-of-order chain confuses
older clients, and over-broad wildcards expand the blast radius of any
future key compromise.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Revoked certificate presented |
CRITICAL |
OCSP responder says "revoked" |
RFC 6960 |
| Missing or invalid OCSP staple |
HIGH |
No status_request response on production |
RFC 6066, CA/B BR |
| Fewer than 2 SCTs embedded |
HIGH |
CT-policy violation (Chrome enforces) |
RFC 6962, CA/B Baseline Reqs |
| Intermediate served out of RFC 5246 order |
MEDIUM |
Server sends root before leaf |
RFC 5246 §7.4.2 |
| AIA extension missing |
MEDIUM |
No CA Issuers / OCSP URL in cert |
RFC 5280 §4.2.2.1 |
| Over-broad wildcard |
HIGH |
Scope of 2-level or wider (e.g., *.com) |
CA/B Baseline Reqs §3.2.2 |
| Wildcard at apex SAN |
LOW |
*.example.com without example.com |
RFC 6125 §6.4.3 |
| Key Usage missing digitalSignature |
MEDIUM |
KU bit absent for TLS server cert |
RFC 5280 §4.2.1.3 |
| Cert chain longer than 4 |
LOW |
Performance + trust expansion |
CA/B Baseline Reqs |
Prerequisites
- Python 3.9+ with
cryptography library
openssl CLI 1.1.1+ (for OCSP query + chain enumeration)
- Authorization for non-local targets (see
references/AUTHORIZATION.md
in skill #1 analyzing-tls-config for the canonical pattern)
Instructions
Step 1 — Confirm Authorization
Active scan; ask the user verbatim:
> "Do you have authorization to perform TLS testing on this target?
> I need confirmation before proceeding."
Step 2 — Run the scanner
python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-ssl-cert-issues/scripts/check_cert_chain.py \
https://target.example.com \
--authorized
Options:
Scan a source tree for weak cryptographic primitives: MD5 / SHA-1 used for security purposes, DES / 3DES / RC4 ciphers, ECB block mode, custom-built crypto (XOR loops, hand-rolled HMAC), hardcoded IVs, predictable random (Math.
ReadBash(python3:*)GlobGrep
Detecting Weak Cryptography
Overview
Weak cryptography (CWE-327 Use of a Broken or Risky Cryptographic
Algorithm, CWE-330 Use of Insufficiently Random Values) shows up
when engineers use the convenient API instead of the cryptographic
one. hashlib.md5(password) is faster to type than the correct
bcrypt/argon2 invocation; Math.random() returns a number quickly
without needing to know about crypto.randomBytes().
The fix is universal: use the modern primitive. SHA-256 for general
hashing, bcrypt/argon2/scrypt for passwords, AES-GCM for encryption,
HMAC-SHA256 for signing, secrets / crypto.randomBytes /
SecureRandom for randomness.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| MD5 used in security context |
HIGH |
hashlib.md5, MessageDigest.MD5, CryptoJS.MD5 |
CWE-327 |
| SHA-1 used in security context |
HIGH |
hashlib.sha1, etc. |
CWE-327 |
| DES / 3DES cipher |
CRITICAL |
DESCrypto, "DES/CBC", "DESede" |
CWE-327 |
| RC4 cipher |
CRITICAL |
"ARC4", "RC4" |
CWE-327 |
| AES ECB mode |
CRITICAL |
"AES/ECB" or MODE_ECB |
CWE-327 |
| Hardcoded IV (initialization vector) |
CRITICAL |
IV literal in source |
CWE-329 |
| Custom XOR-based "encryption" |
CRITICAL |
XOR loop over bytes |
CWE-327 |
| Predictable random for crypto seed |
CRITICAL |
Math.random / java.util.Random / random.random for keys |
CWE-330 |
| TLS cert verification disabled |
CRITICAL |
verify=False, rejectUnauthorized:false, ServerCertificateValidationCallback returning true |
CWE-295 |
| Hardcoded HMAC secret |
HIGH |
Long literal in HMAC constructor |
CWE-321 |
| Insecure password hashing (no salt, no KDF) |
CRITICAL |
hashlib.sha256(password) without bcrypt/argon2 |
CWE-916 |
Prerequisites
- Python 3.9+
- Source tree on local filesystem
Instructions
Run
python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-weak-cryptography/scripts/scan_weak_crypto.py /path/to/repo
Options: --output, --format, --min-severity, --include-tests,
--languages
Identify the server software, framework, and component versions a target is running from its HTTP response signatures — Server header, X-Powered-By, Via, X-AspNet-Version, X-Runtime, X-Drupal-Cache, X-Generator, Set-Cookie name patterns, error-page artwork, HTTP method behavior signatures.
ReadBash(python3:*)Bash(curl:*)
Fingerprinting Server Software
Overview
Version disclosure is the cheapest recon an attacker buys. A single
GET request returns the Server: header, the X-Powered-By: header,
and any framework-default cookies. From those three signals the
attacker derives: web server family + exact version, app-framework +
version, language runtime + version. That maps directly to a CVE
catalog query: every published CVE affecting any of those components,
filtered to ones an unauthenticated attacker can trigger.
The fix is operationally trivial (one line in nginx, one line in
Apache, one line in IIS) but the discipline isn't universal. This
skill enumerates the signals + reports each disclosure with the
severity matching how much it enables follow-on attack.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Server header discloses version |
MEDIUM |
Server: nginx/1.18.0 or similar with explicit version |
CWE-200 |
| Server header discloses minor version |
LOW |
Server: nginx (no version) |
CWE-200 |
| X-Powered-By discloses framework version |
MEDIUM |
X-Powered-By: PHP/7.4.21, Express, ASP.NET |
CWE-200 |
| X-AspNet-Version present |
HIGH |
Specific dotnet runtime version |
CWE-200 |
| X-Runtime / X-Rails / X-Django headers present |
LOW |
Framework identification, no version |
CWE-200 |
| X-Generator: drupal/wordpress + version |
MEDIUM |
CMS family + version disclosure |
CWE-200 |
| Via header discloses proxy chain |
LOW |
Reveals upstream architecture (Varnish, Squid, CloudFront) |
CWE-200 |
| Framework-default Set-Cookie pattern |
LOW |
PHPSESSID, JSESSIONID, connect.sid, etc. |
CWE-200 |
| Error page reveals stack trace |
HIGH |
5xx response body contains source file paths or framework banner |
CWE-209 |
| HTTP/2 server-push fingerprint |
LOW |
HTTP/2 :server pseudo-header with version |
CWE-200 |
| ETag format identifies cluster member |
LOW |
Apache-style hex ETags reveal node |
CWE-200 |
Prerequisites
- Python 3.9+ with
requests
- Authorization for non-local targets
Compose an exec-readable summary from a unified findings JSONL plus the OWASP coverage report.
ReadWriteBash(python3:*)Glob
Generating Executive Summary
Overview
The vulnerability report is comprehensive — every finding, full
detail, every reference. The C-level reader doesn't open it. They
ask their security lead "what should I tell the board?" The
security lead needs a one-page answer.
That one-page answer is the executive summary. It states the
engagement's bottom line:
- A single risk score (0-100)
- Headline counts by severity
- Top-3 remediation priorities, each with rough effort + impact
- OWASP Top 10 coverage (where the work landed)
- Engagement scope and authorization summary (what was tested,
under what authority, in what window)
- Next steps the customer's organization should take
The summary doesn't omit anything important; it just compresses.
The vulnerability report remains the deep artifact for anyone who
needs the technical detail.
This skill consumes the enriched findings JSONL (after OWASP
mapping) + the OWASP coverage report + the ROE, computes the risk
score, picks the top remediation priorities deterministically,
and renders the document.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Input findings file missing |
CRITICAL |
Source JSONL doesn't exist |
(operational) |
| OWASP coverage report missing |
HIGH |
Coverage referenced but not present |
(operational) |
| ROE missing |
MEDIUM |
Can still generate summary but lacks scope/authz context |
(operational) |
| Exec summary written cleanly |
INFO |
Confirmation |
(informational) |
| Risk score >75 (high engagement risk) |
HIGH |
Computed risk score elevated |
(advisory) |
| Risk score >90 (critical engagement risk) |
CRITICAL |
Engagement exposed material risk; needs urgent action |
(advisory) |
Risk score (0-100) composition
The single risk score is the headline number on the exec summary.
The composition is deterministic and documented:
risk = clamp(0, 100,
20 * count(CRITICAL)
+ 10 * count(HIGH)
+ 3 * count(MEDIUM)
+ 1 * count(LOW)
+ 0 * count(INFO)
+ 5 * (count(distinct OWASP categories touched) - 5 if >5 else 0)
- 10 * 1 if engagement was authorized cleanly and in-scope (governance bonus)
)
The first five terms weight by severity. The OWASP-coverage term
adds 5 points per category beyond 5 (a broader-finding engagement
implies broader risk surface). The governance bonus is a -1
Annotate every pentest finding with its OWASP Top 10 (2021) category by applying a deterministic rule table keyed on source skill, finding category, detail keywords, and CWE identifier when present.
ReadWriteBash(python3:*)Glob
Mapping Findings to OWASP Top 10
Overview
OWASP Top 10 is the canonical taxonomy of web-application risk
categories. Every customer-facing pentest report has an "OWASP
coverage" section because customers, auditors, and insurers
expect to see findings mapped against the Top 10. Without the
mapping, a long list of CVEs and misconfigurations reads as
noise; with the mapping, it reads as a structured assessment.
This skill applies a deterministic rule table to annotate each
finding with its OWASP category. Rules are keyed on:
- Source skill ID (a finding from
auditing-npm-dependencies
is almost always A06 — Vulnerable and Outdated Components).
- Finding category (the per-skill category tag, e.g.
dependency-vulnerability, engagement-scope).
- CWE identifier if present (CWE → OWASP is a well-trodden
mapping; OWASP themselves publish the cross-walk).
- Detail keywords as a fallback when the above don't
determine a category.
Output is an enriched JSONL (each finding gets an owasp_category
field) plus a coverage report showing how the engagement's
findings distribute across A01-A10. UNMAPPED findings are
surfaced for human review — extend the rule table or accept the
finding as cross-cutting (some findings genuinely don't fit a
single A0X bucket).
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Finding unmapped after rule application |
INFO |
No rule matched the finding |
(operational) |
| Source JSONL unparseable |
HIGH |
Standard JSONL parse error |
(operational) |
| Annotation written back successfully |
INFO |
Confirmation per source file |
(informational) |
| Coverage report generated |
INFO |
Coverage report path emitted |
(informational) |
| Engagement covers all 10 categories |
INFO |
At least one finding in each A01-A10 bucket |
(positive observation) |
| Engagement covers <5 of 10 categories |
MEDIUM |
Suggests scope may have been narrow |
(informational) |
OWASP Top 10 (2021) reference
| Category |
Description |
| A01:2021 |
Broken Access Control |
| A02:2021 |
Cryptographic Failures |
| A03:2021 |
Injection |
| A04:2021 |
In
Orchestrate a penetration test by routing user intent to one or more of the 25 narrow skills in this pack.
ReadWriteEditGlobGrepBash(python3:*)Bash(pip:*)Bash(npm:*)Bash(bandit:*)Bash(pip-audit:*)Bash(pipdeptree:*)Bash(gpg:*)Bash(tar:*)
Performing Penetration Testing
Overview
v3.0.0 of penetration-tester is a 25-skill pack. Each skill is
narrow and heavy-hitter compliant (≥250 LOC scripts, ≥2 reference
docs, 8-field SKILL.md frontmatter). This orchestrator routes
user intent to the right combination of narrow skills.
The 25 skills group into 7 clusters:
- Cluster 0 — this orchestrator
- Cluster 1 (5 skills) — Network / transport
- Cluster 2 (4 skills) — Information disclosure
- Cluster 3 (6 skills) — Source-code static analysis
- Cluster 4 (4 skills) — Dependency analysis
- Cluster 5 (3 skills) — Engagement governance
- Cluster 6 (3 skills) — Reporting
Cluster 5 + 6 are the v3 additions versus v2. Cluster 5 runs
BEFORE any scan and refuses to proceed if authorization is
missing or scope is malformed. Cluster 6 runs AFTER scans and
produces the deliverable artifacts (vulnerability report, OWASP
coverage report, executive summary, chain-of-custody archive).
Instructions
The orchestrator's job is intent routing — given a user utterance, decide which of the 25 narrow skills to invoke and in what order. Four steps:
Step 1 — Parse the user intent
Match the utterance against the intent-routing table below. The leftmost matching row determines the routing. If no exact match, default to the cluster-1-4 governance-first sequence and pare back based on context.
Step 2 — Run authorization-first
Before any cluster 1-4 scan invocation, run confirming-pentest-authorization. If it emits any CRITICAL finding, HALT — do not invoke any scan skill. The user must resolve the authorization issue before proceeding.
Step 3 — Run the matched skills in order
Invoke each skill from the routing-table row, in the listed order. Each skill emits its findings as JSON/JSONL/markdown via lib/report.py. Persist per-skill output into engagement/findings/-.jsonl so the cluster 6 skills can consume them.
Step 4 — Compose deliverables
After scan skills complete, run cluster 6 in sequence: mapping-findings-to-owasp-top10, then composing-vulnerability-report, then generating-executive-summary, then recording-pentest-engagement for the chain-of-custody archive.
Intent routing (the table)
| User intent / trigger phrase |
Skills to invoke (in order) |
| "pentest", "full security scan" |
confirming-pentest-authorization → defining-pentest-scope → cluster 1-4 (all) → mapping-findings-to-owasp-top10 → composing-vulnerability-report → generating-executive-summary → recording-pentest-engagement |
Probe a target for HTTP methods that should not be enabled in production — TRACE (XST attack), unrestricted PUT/DELETE, DEBUG/CONNECT, WebDAV (PROPFIND/MKCOL/COPY/MOVE), and Allow header enumeration.
ReadBash(python3:*)Bash(curl:*)
Probing Dangerous HTTP Methods
Overview
Most HTTP methods beyond GET/POST/HEAD are vestigial — leftover from
WebDAV authoring stacks of the early 2000s, debugging features in
legacy servers, or default-enabled methods nobody disabled at install
time. Each enabled method that the application doesn't use is an
attack surface: TRACE enables Cross-Site Tracing (XST), PUT enables
arbitrary file upload to unprotected paths, CONNECT enables proxy
abuse against internal services, WebDAV enables directory manipulation.
This skill probes the canonical method set and grades each based on
its presence and response.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| TRACE method enabled |
HIGH |
TRACE returns 200 with request echo |
OWASP A05:2021, CWE-693 |
| PUT method enabled outside API path |
HIGH |
PUT returns 200/201/204 on non-API path |
CWE-434 |
| DELETE method enabled outside API path |
HIGH |
DELETE returns 200/204 on non-API path |
CWE-285 |
| CONNECT method enabled |
CRITICAL |
CONNECT returns 200 (proxy abuse open) |
CWE-441 |
| DEBUG method enabled |
HIGH |
DEBUG returns response (legacy IIS / dev servers) |
CWE-489 |
| WebDAV methods enabled (PROPFIND/MKCOL/COPY/MOVE) |
HIGH |
Any return 207 or 201 |
CWE-538 |
| Allow header discloses unused methods |
LOW |
OPTIONS Allow includes methods app doesn't use |
CWE-200 |
| OPTIONS returns full method enumeration |
LOW |
Allow:* or broad list |
CWE-200 |
Prerequisites
- Python 3.9+
- Authorization for non-local targets
Instructions
Step 1 — Confirm authorization
"Do you have authorization to perform HTTP method probing on this
target? I need confirmation before proceeding."
Step 2 — Run the scanner
python3 ${CLAUDE_PLUGIN_ROOT}/skills/probing-dangerous-http-methods/scripts/probe_methods.py \
https://example.com \
--authorized
Options:
Usage: probe_methods.py URL [OPTIONS]
Options:
--authorized Attest authorization (required)
--output FILE
--format FMT json | jsonl | markdown (default: markdown)
--min-severity SEV (default: info)
--timeout SECS
--is-api Treat URL as API endpoint (relaxes PUT/DELETE checks)
By default the scanner treats the
Package an engagement's findings, scan outputs, evidence, and signed ROE into a timestamped archive with a SHA-256 manifest covering every file.
ReadBash(python3:*)Bash(tar:*)Bash(gpg:*)Glob
Recording Pentest Engagement
Overview
A penetration test produces a lot of artifacts: scan outputs in
multiple formats, screenshots showing the state of vulnerable
pages, raw tool logs (nmap, Burp, custom scripts), the ROE and any
amendments, exec-summary docs, and the findings themselves. Six
months after the engagement closes, a question arises — sometimes
benign ("can you remind me what we found?"), sometimes adversarial
("the customer claims we accessed an out-of-scope system; show us
the logs"). The answer needs to be: "yes, here's the archive, and
here's cryptographic proof it hasn't been touched since the
engagement closed."
This skill packages the engagement directory into a single
timestamped archive with a SHA-256 manifest covering every file.
Optionally signs the manifest with GPG. The result is a portable,
self-verifying record of what the engagement produced.
The skill also surfaces inconsistencies that would weaken the
chain-of-custody claim: out-of-tree paths referenced in findings
(meaning the finding refers to a file not actually in the archive),
files in the directory not listed in the manifest, manifest
entries whose hashes don't match. These are HIGH findings — they
mean the archive is incomplete or has been modified after the
fact, neither of which is acceptable for evidence purposes.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| File in tree not in manifest |
HIGH |
Found during walk; manifest entry missing |
(evidence integrity) |
| Manifest entry hash mismatch |
CRITICAL |
Computed SHA-256 differs from manifest |
(evidence integrity) |
| Manifest entry without file |
HIGH |
Manifest lists a path that doesn't exist |
(evidence integrity) |
| Findings reference out-of-tree path |
MEDIUM |
A finding's evidence field points to a file not in the archive |
(evidence completeness) |
| Symlink in tree |
MEDIUM |
Symlinks break archive portability and integrity |
(evidence integrity) |
| Empty file in tree |
INFO |
0-byte file; possibly an export error |
(operational) |
| Archive package complete |
INFO |
All checks pass |
(positive confirmation) |
| Manifest signed |
INFO |
GPG signature present and valid form |
(positive confirmation) |
Prerequisites
Scan a source-code tree for hardcoded credentials embedded in source files: AWS access keys, GitHub tokens, Stripe keys, Slack tokens, Anthropic API keys, OpenAI keys, JWT signing secrets, generic base64-encoded passwords, RSA / SSH private keys, and high-entropy string literals that pattern-match common credential shapes.
ReadBash(python3:*)GlobGrep
Scanning for Hardcoded Secrets
Overview
The single most common cause of credential breach in 2026 remains
hardcoded secrets in source code. Engineers paste an API key into a
config file "just for testing," forget to remove it, commit the
file. The credential is now in the repository's history forever
(git rebase doesn't help if anyone cloned in between) and
extractable by anyone who reaches the repo: contractors,
ex-employees, attackers via .git/ directory exposure (see skill
six), GitHub bot scrapers crawling public repos.
The cost of detection-after-commit is near-zero (free tools exist:
gitleaks, trufflehog, this skill). The cost of detection-before-commit
is also near-zero (pre-commit hooks). The cost of remediation after
the fact is rotating every credential exposed + auditing for
exploitation + potentially notifying customers of breach. The
asymmetry is severe, the discipline is the only constraint.
This skill scans a filesystem tree, matching against a canonical
regex library covering the credential shapes attackers and bots
search for first.
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| AWS access key (AKIA-prefix) |
CRITICAL |
Literal AKIA[0-9A-Z]{16} in any file |
CWE-798 |
| AWS secret access key |
CRITICAL |
40-char base64 in awssecretaccess_key field context |
CWE-798 |
| GitHub personal access token |
CRITICAL |
ghp[A-Za-z0-9]{36} or gho, ghu, ghs, ghr_ |
CWE-798 |
| GitHub app installation token |
CRITICAL |
ghs_[A-Za-z0-9]{36} |
CWE-798 |
| Stripe live key |
CRITICAL |
sklive[A-Za-z0-9]{24,} |
CWE-798 |
| Stripe test key |
MEDIUM |
sktest[A-Za-z0-9]{24,} |
CWE-798 |
| Anthropic API key |
CRITICAL |
sk-ant-api03-[A-Za-z0-9_-]{93} or similar |
CWE-798 |
| OpenAI API key |
CRITICAL |
sk-(proj-)?[A-Za-z0-9_-]{40,} |
CWE-798 |
| Slack bot token |
CRITICAL |
xoxb-[A-Za-z0-9-]+ |
CWE-798 |
| Slack user token |
CRITICAL |
xoxp-[A-Za-z0-9-]+ |
CWE-798 |
| Google API key |
HIGH |
Build a dependency-tree map of a project (npm or Python) and trace the path from each known-vulnerable transitive package back to one or more direct dependencies.
ReadBash(npm:*)Bash(pip:*)Bash(pip-audit:*)Bash(python3:*)Bash(pipdeptree:*)Glob
Tracing Transitive Vulnerabilities
Overview
The auditing-npm-dependencies and auditing-python-dependencies skills
each surface CVEs, but they don't answer the question that actually
decides remediation order: **which of these findings can I clear by
bumping ONE direct dep, and which require deeper intervention?**
That question is the core of supply-chain triage. A high-CVSS CVE
in lodash@4.17.4 is alarming on first read. If it's pulled in by
five different direct deps, the right fix may not be to bump any of
them — it may be a single root-level overrides entry pinning
lodash@^4.17.21. The triage discussion goes very differently when
you can quote: "this CVE is reachable via 5 paths, all of which
flow through webpack, which has a fixed version available." That
shifts a project-wide panic to a one-line PR.
This skill walks the project's dependency graph (via npm ls,
pipdeptree, or equivalent), intersects it with the CVE findings
already produced by the per-language audit skills, and emits a
trace report that includes:
- For each CVE: the full path(s) from direct dep → ... → vulnerable package
- For each direct dep: the count of CVEs reachable through it
- "Highest-leverage upgrade" recommendation — the single direct-dep
bump that clears the most findings at once
- "Unreachable" findings — CVEs whose vulnerable version range is
forced by EVERY parent in the path, requiring overrides or
vendor-patch
- "Deep transitive" findings (≥3 levels from a direct dep) — these
are highest-risk for hidden surprises because the relationship to
your code is most opaque
When the skill produces findings
| Finding |
Severity |
Threshold |
Affected control |
| Critical CVE at deep transitive depth (≥3) |
HIGH |
Depth ≥3 + severity CRITICAL — blast radius unclear |
CWE-1395 |
| High CVE reachable only via overrides |
HIGH |
No direct-dep version clears the finding |
CWE-1395 |
| Multi-CVE direct-dep hotspot |
MEDIUM |
Single direct dep is ancestor for ≥3 separate CVEs |
(informational) |
| Direct-dep bump clears N findings |
INFO |
Reports the recommended bump |
(operational) |
| Unreachable CVE (no fix in any reachable version) |
HIGH |
Finding has no fix-available across the whole graph |
CWE-1395 |
| Circular dep with CVE |
MEDIUM |
Cycle in the dep graph involves a vulnerable package
How It Works
Check security headers on a URL:
> Check the security headers on https://example.com
Audit project dependencies:
> Audit the dependencies in this project for vulnerabilities
Scan code for security issues:
> Scan this codebase for hardcoded secrets and security issues
Full security audit:
> Run a full security audit on this project
Ready to use penetration-tester?
|
|
|
|
|
|
|