skills/security-review/SKILL.md
Run reusable cross-project security review with profile detection, OWASP Dependency-Check, ZAP container scanning, and risk-gated reporting
npx skillsauth add jankneumann/agentic-coding-tools security-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Run a reusable security review workflow across repositories. This skill auto-detects project profile(s), executes compatible scanners, normalizes findings, and applies a deterministic risk gate.
The skill operates in two complementary modes:
Both modes are mutually reinforcing: the preventive checklist eliminates the easy bugs so the scanners surface the hard ones. Run preventive mode on every change; run scanner-runner mode at integration boundaries.
Adopted from the security-and-hardening reference skill. Use this section while authoring or reviewing code that touches authentication, authorization, input validation, secrets, network exposure, or data persistence.
The boundary system replaces ad-hoc judgment with a tiered policy. Map every security-sensitive operation to one of the tiers below.
These are always-correct defaults; deviating from them requires explicit justification in the change description.
? placeholders).pydantic / zod / JSON Schema), not deep in business logic.subprocess.run([...]) — never shell=True with concatenated user data.Operations in this tier are sometimes correct but always risky. Pause and request confirmation before proceeding; document the approval in the PR.
These are absolute prohibitions. Treat any code that crosses these lines as broken and refuse to merge.
eval() / exec() / Function() on attacker-controlled or external input.verify=False, rejectUnauthorized: false).Apply this checklist to every meaningful change. The deeper, item-level guidance lives in references/security-checklist.md — use that file as the authoritative source when triaging an audit finding.
eval / dynamic SQL / os.system on user input..env in source control.For the deeper, language-specific checks behind each item, consult references/security-checklist.md.
$ARGUMENTS - Optional flags:
--repo <path> (default: current directory)--out-dir <path> (default: <repo>/docs/security-review)--profile-override <profiles> (for example python,node)--fail-on <info|low|medium|high|critical> (default: high)--zap-target <url-or-spec> (required for ZAP execution)--zap-mode <baseline|api|full> (default: baseline)--change <change-id> (optional; writes OpenSpec artifact to openspec/changes/<id>/security-review-report.md)--openspec-root <path> (optional override when resolving OpenSpec change directory)--bootstrap <auto|never> (default: auto)--apply-bootstrap (execute install commands, otherwise print-only)--allow-degraded-pass (allow pass when scanners are unavailable and no threshold findings exist)--dry-runScripts live in <agent-skills-dir>/security-review/scripts/. Each agent runtime substitutes <agent-skills-dir> with its config directory:
.claude/skills.codex/skills.gemini/skillsIf scripts are missing, run skills/install.sh to sync them from the canonical skills/ source.
<agent-skills-dir>/security-review/scripts/install_deps.sh<agent-skills-dir>/security-review/docs/dependencies.mdUse docs/coordination-detection-template.md as the shared detection preamble.
CAN_* flag is trueAt skill start, run the coordination detection preamble and set:
COORDINATOR_AVAILABLECOORDINATION_TRANSPORT (mcp|http|none)CAN_LOCK, CAN_QUEUE_WORK, CAN_HANDOFF, CAN_MEMORY, CAN_GUARDRAILSIf CAN_GUARDRAILS=true, run an informational guardrail pre-check before scanners:
check_guardrails"<skill-base-dir>/../coordination-bridge/scripts/coordination_bridge.py" try_check_guardrails(...)Pre-check target text should summarize intended scan commands and any write actions (report generation paths, temp outputs).
Phase 1 behavior:
python3 <agent-skills-dir>/security-review/scripts/detect_profile.py --repo <path> --pretty
python3 <agent-skills-dir>/security-review/scripts/build_scan_plan.py \
--repo <path> \
--zap-target <url-or-spec> \
--zap-mode baseline \
--fail-on high \
--pretty
<agent-skills-dir>/security-review/scripts/check_prereqs.sh --json
If requirements are missing:
# print-only by default
<agent-skills-dir>/security-review/scripts/install_deps.sh --components java,podman,dependency-check
# execute install commands
<agent-skills-dir>/security-review/scripts/install_deps.sh --apply --components java,podman,dependency-check
python3 <agent-skills-dir>/security-review/scripts/main.py \
--repo <path> \
--out-dir docs/security-review \
--fail-on high \
--zap-target <url-or-spec> \
--zap-mode baseline \
--change <change-id> \
--bootstrap auto
Outputs (default under <repo>/docs/security-review/):
aggregate.jsongate.jsonsecurity-review-report.jsonsecurity-review-report.mdopenspec/changes/<change-id>/security-review-report.mdDry-run behavior:
--dry-run still writes deterministic files under docs/security-review/.--dry-run does not overwrite openspec/changes/<change-id>/security-review-report.md.PASS: no findings at/above threshold and scanner execution acceptable.FAIL: findings met/exceeded threshold.INCONCLUSIVE: scanner execution incomplete (unless degraded pass is explicitly allowed).--zap-target marks ZAP as unavailable and yields INCONCLUSIVE unless --allow-degraded-pass is set.Dependency-Check adapter (native or container fallback):
<agent-skills-dir>/security-review/scripts/run_dependency_check.sh --repo <path> --out <dir>
python3 <agent-skills-dir>/security-review/scripts/parse_dependency_check.py --input <dir>/dependency-check-report.json --pretty
ZAP adapter (container runtime):
<agent-skills-dir>/security-review/scripts/run_zap_scan.sh --target <url-or-spec> --out <dir> --mode baseline
python3 <agent-skills-dir>/security-review/scripts/parse_zap_results.py --input <dir>/zap-report.json --pretty
python3 -m pytest <agent-skills-dir>/security-review/tests -q
openspec validate add-security-review-skill --strict
| Rationalization | Why it's wrong |
|---|---|
| "Dependency-Check passed, so the change is secure" | SCA only catches known-CVE'd dependencies. It says nothing about your authn/authz logic, your input validation, or the shell injection you wrote yesterday. Run preventive mode AND scanner mode. |
| "I'll skip the OWASP checklist — this PR is small" | The most expensive vulnerabilities ship in small PRs (a one-line verify=False, a f"... {user_input} ..." SQL string). Small PRs are exactly when humans skip review; the checklist exists to compensate. |
| "We don't have a threat model, so I can't tell what tier this falls into" | When in doubt, treat the operation as Tier 2 (ask first). Tier-3 prohibitions (eval, hardcoded secrets, TLS bypass) are absolute and don't require a threat model to recognize. |
| "ZAP scan target isn't deployed yet — I'll skip the scan" | Run preventive mode anyway. ZAP-INCONCLUSIVE is fine for a PR that doesn't add new endpoints; it is not fine when the PR is the new endpoint. Wire ZAP into staging before merge. |
| "The scanner finding is a false positive — I'll suppress it without a note" | Suppressing without a justification (issue link, threat-model reference, compensating-control description) is how real findings get buried. Always document the suppression in the report. |
subprocess call with shell=True or any new SQL string that includes f"..." / + / % formatting with non-literal data — Tier 3 prohibition.verify=False, rejectUnauthorized: false, or InsecureRequestWarning suppression appearing anywhere outside a clearly-labelled local-test fixture — Tier 3 prohibition.package.json / pyproject.toml / Cargo.toml that handles auth, crypto, or sessions, without a note in the PR explaining why and confirming it has recent commits and no open critical advisories.gate.json reports INCONCLUSIVE and --allow-degraded-pass was applied without a justification in the PR description.request.body, headers["Authorization"], request.cookies, or password-bearing form fields — Tier 2 violation that often slips through review..env file, private key, or kubeconfig appearing in git status for the PR.rg "shell=True|verify=False|eval\(|exec\(") and zero violations remain in the PR diff.gate.json with PASS (or INCONCLUSIVE with --allow-degraded-pass AND a written justification).references/security-checklist.md was consulted for the relevant item-level checks (cite the section heading) when the change touches an OWASP category.development
Open the artifacts relevant to a review (OpenSpec proposal, branch changes, or explicit paths) in VS Code, in a curated read-order, in the right worktree.
tools
Render and seed coordinator-owned task status block in OpenSpec tasks.md
testing
User-invocable skill that omits the tail block
tools
Missing several required keys