Harden Codebase Skill Active security hardening — scan the existing repository for vulnerabilities and forward-facing threats, then propose concrete remediations the user can approve, defer, or file. This skill is the engine behind . It complements the Claude Code built-in (which scans the pending diff) by sweeping the whole repository against citation-backed checks rather than line-level review of in-flight code. When To Use - Quarterly security-posture audits. - Before tagging a release that touches sensitive code paths. - After a published advisory affects the language ecosystem. - When on…

\n```\n\n## Severity defaults\n\n| Family | Default | Justification |\n|--------|---------|---------------|\n| DEP04, DEP07, CI07, CO07 | LOW | operational hygiene; no exploit narrative |\n| DEP01, DEP02, SEC01, SEC02, CI02, CI03, CO01, CO02 | MEDIUM | one defense-in-depth layer missing |\n| DEP03, SEC03, SEC04, CI01, CI06, CO03 | HIGH | exploitable supply-chain or privilege issue |\n| SEC03 with leaked active credential | CRITICAL | active exploit path |\n\nA finding can be promoted from default with evidence (e.g.,\nDEP01 promoted to HIGH if the lockfile is missing AND auto-merge\nis enabled on dep PRs).\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5415,"content_sha256":"15db915340fc70971fb4f66daeed35cd68cfba093abff3d8ab7b5d0f4d3026a5"},{"filename":"modules/frontier-checks.md","content":"# Frontier Hardening Checks (2025-2026)\n\nForward-facing checks that defend against threats just emerging\nin production. Findings here are usually MEDIUM by default\nbecause exploitation is non-trivial; promote to HIGH when the\ncodebase has a high-value attack surface (auth provider, signing\nservice, data plane).\n\n## Post-quantum migration readiness\n\nThe NSA CNSA 2.0 timeline targets quantum-resistant crypto for\nNSS by 2030; PCI DSS 4.0.1 expects an inventory by 2026. Most\napplication code is not the right place to swap algorithms, but\nthe *crypto-agility* posture is.\n\n| ID | Check | Citation | Detection |\n|----|-------|----------|-----------|\n| PQ01 | Signing/verification has a single hard-coded algorithm | NIST IR 8547 | `algorithms = [\"RS256\"]` or `algorithms = [\"EdDSA\"]` literal in JWT/JWS code |\n| PQ02 | Algorithm selection driven by config, not code | NIST IR 8547 | move the algorithm list behind a `signing_algorithms` config field |\n| PQ03 | Inventory of crypto APIs in the repo | NIST CNSA 2.0 | no `docs/crypto-inventory.md` or equivalent |\n| PQ04 | TLS clients accept algorithm downgrade silently | CWE-757 | `requests` / `reqwest` defaults without minimum-TLS pin |\n\nThe proposal for PQ02 is usually a small refactor: move\n`algorithms = [\"EdDSA\"]` into a config table the operator can\noverride. The skill does not propose ML-DSA / Falcon migration\nin application code (still specialist work).\n\n## LLM and agentic supply chain\n\nA new failure mode in 2025: AI assistants suggest dependencies\nthat look plausible but do not exist (or are typosquats). The\nchecks below defend the development pipeline itself.\n\n| ID | Check | Citation | Detection |\n|----|-------|----------|-----------|\n| LLM01 | Index pinning to defeat dependency confusion | OWASP LLM Top 10 #08 | `pyproject.toml` lacks `[[tool.uv.index]]` priority order |\n| LLM02 | New deps require human review | OWASP LLM Top 10 #08 | no CI rule blocking auto-merge on dep PRs |\n| LLM03 | LLM SDK calls validate role/instruction boundaries | OWASP LLM Top 10 #01 | system prompt concatenated with user input without separator/role |\n| LLM04 | Tool-use response sanitization | OWASP LLM Top 10 #02 | tool output rendered to UI/terminal without escape |\n| LLM05 | MCP server allowlist of tools | OWASP LLM Top 10 #02 | MCP config mounts every tool from a server (no allowlist) |\n| LLM06 | Agent action audit trail | OWASP LLM Top 10 #06 | no log of tool invocations with inputs |\n\n## Sandbox / isolation posture\n\nFor codebases that execute user-supplied or AI-supplied code:\n\n| ID | Check | Why | Today's option |\n|----|-------|-----|----------------|\n| SB01 | User code runs in same process as host | host privilege escalation | Pyodide WASM (Python), wasmtime (Rust) |\n| SB02 | Network egress unrestricted from sandbox | data exfiltration | gVisor egress policy, NetworkPolicy in K8s |\n| SB03 | Filesystem capabilities ambient | path-based attacks | `cap-std` (Rust), bind-mount only required dirs |\n| SB04 | Resource limits absent | DoS via runaway workload | cgroup `memory.max`, `cpu.max`; `prlimit` in containers |\n\n## eBPF / runtime security hooks\n\nProduction codebases benefit from runtime monitoring even when\nthe static defenses are good. The skill flags absence:\n\n| ID | Check | Tool | What it catches |\n|----|-------|------|-----------------|\n| RT01 | Runtime detection layer present | Falco / Tetragon / Tracee | unexpected syscalls, container escapes |\n| RT02 | App emits structured audit events | OpenTelemetry traces with semantic conventions | post-incident reconstruction |\n| RT03 | Deployment includes seccomp/apparmor profile | runtime config | exploit blast-radius capping |\n\n## Differential-privacy / PETs awareness\n\nFor codebases that handle aggregable user data (analytics, ML\ntraining, telemetry):\n\n| ID | Check | Citation | Signal |\n|----|-------|----------|--------|\n| DP01 | Aggregations expose per-user values without noise | NIST SP 800-188 | counts/means published without DP budget |\n| DP02 | Logs retain raw PII beyond retention window | GDPR Art. 5 | log retention config absent or > 30 days for PII fields |\n\n## Memory-safety migration triage (when C/C++ is present)\n\nPer CISA's \"Secure by Design\" pledge and the ONCD memory-safety\nreport (Feb 2024), new code in safety-critical contexts should\nbe in a memory-safe language by default. The skill flags the\nopportunity, not the migration:\n\n| ID | Check | Signal | Proposal |\n|----|-------|--------|----------|\n| MS01 | C/C++ code paths handle untrusted input | parser, network code in C/C++ | rewrite or wrap behind a Rust shim |\n| MS02 | C-style string handling | `strcpy`, `sprintf`, `gets` | move to Rust or use `safestr`/`absl::Cord` |\n\n## Output\n\nFindings here use the same schema as the other modules. Severity\nis **MEDIUM** by default; promote to HIGH when:\n\n- The repo is an auth/signing/credentialing service (PQ findings)\n- The repo ships an MCP server or agent harness (LLM findings)\n- The repo has untrusted-code-exec posture (SB findings)\n- The repo handles regulated PII (DP findings)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5056,"content_sha256":"f2a1abe0f2c6d9c757c5beb00f78030dc66a0d7880c2efa1677794548ced7b98"},{"filename":"modules/nist-controls.md","content":"# NIST and CWE Citation Backbone\n\nEvery finding in a hardening report carries a citation. This\nmodule is the lookup table.\n\n## NIST SSDF (SP 800-218) practice mapping\n\nThe Secure Software Development Framework defines four practice\ngroups: Prepare the Organization (PO), Protect Software (PS),\nProduce Well-Secured Software (PW), Respond to Vulnerabilities\n(RV). Findings map to PW and RV most often.\n\n| Practice | What it requires | Detector signal |\n|----------|------------------|-----------------|\n| PW.4 | Reuse existing well-secured software | dependencies pinned, scanned, attested |\n| PW.5 | Create source code aligned with secure practices | linter enforces auth/crypto/serialization rules |\n| PW.6 | Configure compilation, build processes, links | RUSTFLAGS hardening, Python `-W error`, reproducible builds |\n| PW.7 | Review and analyze human-readable code | SAST run in CI; findings tracked |\n| PW.8 | Test executable code | fuzz coverage, mutation tests, property tests |\n| PW.9 | Configure software with secure default settings | yaml SafeLoader, TLS verify on, autoescape on |\n| RV.1 | Identify, confirm vulnerabilities on a continuous basis | dependency scanner runs on every push |\n| RV.2 | Assess, prioritize, remediate vulnerabilities | severity policy, SLA per severity |\n| RV.3 | Analyze vulnerabilities to identify root causes | post-incident notes feed PW.4-9 |\n\nThe skill's executive summary lists each practice and whether the\ncodebase has at least one detector firing for it. Coverage \u003c80%\nof PW.4-PW.9 is itself a finding (RV.1 unmet).\n\n## CWE Top 25 (2024) mapping\n\nThe skill prioritizes detectors that map to the CWE Top 25 most\ndangerous software weaknesses. Per-finding citations name the\nspecific CWE, not just \"Top 25.\"\n\n| CWE | Title | Languages most often hit |\n|-----|-------|--------------------------|\n| CWE-79 | Cross-site Scripting | Python, JS |\n| CWE-787 | Out-of-bounds Write | Rust unsafe, C/C++ FFI |\n| CWE-89 | SQL Injection | Python, Rust |\n| CWE-352 | CSRF | Python web frameworks |\n| CWE-22 | Path Traversal | All |\n| CWE-125 | Out-of-bounds Read | Rust unsafe, C/C++ FFI |\n| CWE-78 | OS Command Injection | Python (subprocess), shell scripts |\n| CWE-416 | Use After Free | Rust unsafe, C/C++ |\n| CWE-862 | Missing Authorization | Web layer |\n| CWE-434 | Unrestricted File Upload | Web layer |\n| CWE-94 | Code Injection | Python (eval/exec), template engines |\n| CWE-20 | Improper Input Validation | All |\n| CWE-77 | Command Injection | All shell-out paths |\n| CWE-287 | Improper Authentication | Auth layer |\n| CWE-269 | Improper Privilege Management | Container, sudo |\n| CWE-502 | Deserialization of Untrusted Data | Python, Java |\n| CWE-200 | Exposure of Sensitive Information | Logs, errors, telemetry |\n| CWE-863 | Incorrect Authorization | Web layer |\n| CWE-918 | Server-Side Request Forgery | URL fetchers |\n| CWE-119 | Improper Restriction of Operations within Memory Buffer | Rust unsafe, C/C++ |\n| CWE-476 | NULL Pointer Dereference | Rust unsafe, C/C++ |\n| CWE-798 | Use of Hard-coded Credentials | All |\n| CWE-190 | Integer Overflow or Wraparound | All |\n| CWE-400 | Uncontrolled Resource Consumption | All |\n| CWE-306 | Missing Authentication for Critical Function | Web/API layer |\n\n## OWASP ASVS level targets\n\nFindings track the ASVS level they aim at:\n\n| Level | Target | Skill default |\n|-------|--------|---------------|\n| L1 | Opportunistic attacker | always |\n| L2 | Targeted attacker | when secrets-bearing config detected |\n| L3 | Determined attacker | only on `--focus all` with `--strict` |\n\n## RustSec advisory database\n\nFor Rust findings, cite the specific advisory ID\n(RUSTSEC-YYYY-NNNN). The `cargo audit` JSON output contains\nthese directly. Use them in the proposal's reversal plan to\nexplain *why* the upgrade is required.\n\n## How findings cite\n\nEach finding's `Citation:` line names:\n\n1. Primary CWE (always)\n2. NIST SSDF practice (always; pick the closest match)\n3. Optional: OWASP ASVS section, RustSec ID, PEP number, CVE\n\nExample:\n\n```\nCitation: CWE-502 (Deserialization of Untrusted Data),\nNIST SSDF PW.7 (Review and analyze human-readable code),\nOWASP ASVS V5.5 (Deserialization Prevention).\n```\n\nA finding with no primary CWE cannot be classified above\nADVISORY severity.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4262,"content_sha256":"4657468ff017eee27367e746f2c48cb8a42275504e018cda3ed996c6ac20a13a"},{"filename":"modules/proposal-shape.md","content":"# Proposal Shape\n\nEvery proposed remediation in a hardening report follows this\nschema. The schema is not optional: a finding without a complete\nproposal cannot be applied (the user can still choose to file or\ndefer it).\n\n## Required fields\n\n| Field | Purpose |\n|-------|---------|\n| `id` | Stable identifier across runs (e.g., `H7`, `PY03`) |\n| `severity` | CRITICAL / HIGH / MEDIUM / LOW / ADVISORY |\n| `citation` | Primary CWE plus NIST SSDF practice (mandatory) |\n| `file` | Single file the proposal touches (multi-file proposals split into siblings) |\n| `lines` | Affected line range, e.g., `42-58` |\n| `detection_signal` | What pattern the scanner saw (in safe-to-quote form) |\n| `proposal` | One-paragraph description of the fix |\n| `diff` | Concrete diff or config snippet, not \"consider doing X\" |\n| `blast_radius` | low / medium / high — see below |\n| `reversal_plan` | Exact command to revert and the conditions to reapply |\n| `expected_test` | Test path that should pass after the change |\n\n## Severity to default disposition\n\n| Severity | Default disposition |\n|----------|---------------------|\n| CRITICAL | apply or file immediately; never advisory |\n| HIGH | propose for apply with prompt |\n| MEDIUM | propose for apply only when `--auto-apply medium` |\n| LOW | file as issue by default |\n| ADVISORY | report only; never proposed |\n\nCRITICAL findings always prompt even under `--auto-apply`.\n\n## Blast radius scale\n\nThe proposal queries `Skill(pensive:blast-radius)` for the\nchange-impact graph and reports one of:\n\n| Tier | Definition |\n|------|------------|\n| **low** | Single file; no public API change; no signature change; no behavior visible to callers |\n| **medium** | Multiple files OR public API addition (new param with default, new method) OR test-only behavior change |\n| **high** | Public API breaking change OR cross-plugin coupling OR config schema change |\n\nHigh-blast-radius proposals require explicit approval even\nunder `--auto-apply`. The skill warns when the radius rises\nabove the user's current `--auto-apply` ceiling.\n\n## Reversal plan template\n\n```\nReversal:\n command: git revert \u003csha> --no-edit\n retry condition: \u003cwhen it would be safe to reapply>\n evidence file: reviews/harden-\u003cdate>.md (this report)\n```\n\nFor config changes that cannot be reverted by `git revert`\nalone (e.g., a CI permission change that runs only on push):\n\n```\nReversal:\n command: git revert \u003csha> --no-edit\n follow-up: re-trigger the workflow on master to confirm the\n permissions are restored\n evidence file: reviews/harden-\u003cdate>.md\n```\n\n## Expected-passing test\n\nEach proposal cites a test that should pass after the change:\n\n- If a test already exists, name it: `tests/unit/x.py::test_y`.\n- If a test must be added, the proposal includes the test code in\n the same diff block. The test must fail against the\n pre-proposal code (RED) and pass after (GREEN).\n\nA proposal without an expected test is downgraded to ADVISORY.\nThis is the harden equivalent of `Skill(imbue:proof-of-work)`'s\nIron Law.\n\n## Approval options (per finding)\n\nWhen the approval gate fires, the user gets:\n\n1. **apply** — apply the diff, commit, run gates, advance.\n2. **file** — create a GitHub issue with the proposal body and\n close out the finding.\n3. **defer** — log to `.harden/backlog.md` for future runs to\n surface again.\n4. **reject** — record a rejection with optional rationale; the\n finding will not surface again unless code changes invalidate\n the rejection.\n\nThe auto-apply ceiling determines which severities skip the gate\nentirely:\n\n```bash\n/harden --auto-apply low # apply LOW automatically\n/harden --auto-apply medium # apply LOW + MEDIUM automatically\n/harden --auto-apply high # apply LOW + MEDIUM + HIGH automatically\n```\n\nCRITICAL is never auto-applied.\n\n## Worked example\n\n```yaml\nid: PY01\nseverity: HIGH\ncitation: \"CWE-502 (Deserialization of Untrusted Data), NIST SSDF PW.7\"\nfile: src/api/loader.py\nlines: 42-44\ndetection_signal: |\n Module imports the Python stdlib unsafe-deserialization helper\n and calls its loads() helper on bytes that originate from the\n request body (data flows from request.body through validate()\n into loader.loads()).\nproposal: |\n Replace the unsafe loader call with json.loads. The payload\n shape is JSON-compatible per the API spec (verified by reading\n the OpenAPI schema for /v1/upload). This eliminates the\n arbitrary-code-execution attack path while preserving the\n positive-path behavior.\ndiff: |\n --- a/src/api/loader.py\n +++ b/src/api/loader.py\n @@ -42,3 +42,5 @@\n -from \u003cstdlib-unsafe-loader> import loads\n +import json\n - obj = loads(payload)\n + obj = json.loads(payload)\nblast_radius: low\nreversal_plan:\n command: \"git revert \u003csha> --no-edit\"\n retry_condition: \"do not retry; the previous form was unsafe by design\"\n evidence_file: \"reviews/harden-2026-05-10.md\"\nexpected_test: tests/unit/api/test_loader.py::test_round_trip_json\n```\n\n## Multi-file proposals\n\nWhen a hardening fix needs touches across multiple files (e.g.,\nadding a `Tier` `Literal` requires updates in classifiers, the\nDORAMetrics dataclass, and the tests), split into sibling\nproposals (PY01a, PY01b, PY01c) with a shared `parent_id`. The\napproval gate applies them as one unit, but each is its own\ncommit so reverts stay surgical.\n\n## What a proposal must NOT do\n\n- Modify generated code, vendored code, or `node_modules`.\n- Touch the changelog except to add a `### Security` bullet.\n- Bump dependency versions beyond the minimum required for the\n fix (a separate proposal per dep upgrade).\n- Introduce a new dependency without an `imbue:proof-of-work`\n evidence trail showing the dep was vetted.\n- Disable existing tests or assertions to make the fix easier.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5761,"content_sha256":"62ade6cecdceceeabbcbb318ac40eb5f3ea66e380ee769e78fc787fedbdfdc66"},{"filename":"modules/python-checks.md","content":"# Python Hardening Checks\n\nDetectors for Python codebases. Each row is a discrete check the\nskill runs; each carries a CWE citation for the report.\n\nThe detection-signal column uses placeholder syntax for patterns\nthat the project's pre-commit security hooks block writing\nliterally. The hooks exist for a reason: this doc describes the\nrules, but the regexes themselves live in code where the safety\nreview treats them as data, not source. If a future contributor\nneeds to inspect the literal patterns, see the corresponding\ndetector module under `plugins/pensive/skills/harden/detectors/`\n(future work; not part of the v1 skill).\n\n## Detection ruleset\n\n| ID | Check | CWE | NIST SSDF | Detection signal |\n|----|-------|-----|-----------|------------------|\n| PY01 | Unsafe deserialization (the stdlib `pickle` family, `marshal`, `shelve`) | CWE-502 | PW.5.1 | `\u003cunsafe-loader>.loads(` on bytes you do not control |\n| PY02 | YAML loaded without a safe Loader | CWE-502 | PW.9 | `yaml.load(` without `Loader=SafeLoader` |\n| PY03 | Code injection via `eval`/`exec`/`compile(...,'exec')` | CWE-94 | PW.5.1 | `\u003ceval-family>(` with a non-constant argument |\n| PY04 | Shell-command injection in a child-process call | CWE-78 | PW.5.1 | bandit B602 / B605: child-process helper invoked with the shell-mode flag and a formatted string |\n| PY05 | SQL injection via string formatting | CWE-89 | PW.5.1 | `cursor.execute(f\"...\")` or `% ` formatting in a query |\n| PY06 | Path traversal in user-supplied paths | CWE-22 | PW.5.1 | `open(user_input)` without `Path.resolve()` and `is_relative_to()` |\n| PY07 | Insecure RNG used for security purposes | CWE-330 | PW.5.1 | `import random` then a token/secret/key generated from it; should be `secrets` |\n| PY08 | TLS verification disabled | CWE-295 | PW.9 | `requests.*(verify=False)`, `ssl.CERT_NONE`, `disable_warnings(InsecureRequestWarning)` |\n| PY09 | Hardcoded credentials | CWE-798 | PW.5.1 | regex match for `api[_-]?key`, `secret`, `token`, `passwd` literals; AWS prefixes (`AKIA...`) |\n| PY10 | Subprocess invocation without timeout | CWE-400 | PW.5.1 | `\u003cchild-proc>.run/Popen` without `timeout=` |\n| PY11 | Tarfile extraction without member filter | CWE-22 | PW.9 | `tarfile.*extractall(` without `filter=` (PEP 706; default became safe in 3.12+) |\n| PY12 | XML XXE / billion-laughs | CWE-611, CWE-776 | PW.9 | `xml.etree.ElementTree.parse(` (use `defusedxml`) |\n| PY13 | Jinja autoescape off in HTML context | CWE-79 | PW.9 | `Environment(autoescape=False)` or `Markup(user_input)` |\n| PY14 | Logging secrets | CWE-532 | PW.5.1 | `logger.*(token)`, `logger.*(password)`, `logger.*(api_key)` |\n| PY15 | Bare `except:` swallowing errors in security paths | CWE-754 | PW.7 | `except:` or `except Exception: pass` in auth or crypto paths |\n| PY16 | Async TOCTOU (time-of-check / time-of-use) | CWE-367 | PW.5.1 | `await is_authorized(...)` then `await act(...)` without re-check |\n| PY17 | Untrusted format string | CWE-134 | PW.5.1 | `(user_input).format(`, f-string built from user input, `\"%\" % user` |\n| PY18 | Insecure temp file | CWE-377 | PW.5.1 | `tempfile.mktemp(` (use `mkstemp` or `NamedTemporaryFile`) |\n| PY19 | `assert` for runtime auth check | CWE-617 | PW.5.1 | `assert user.is_admin` (assert is stripped under `python -O`) |\n| PY20 | `requests` without timeout | CWE-400 | PW.5.1 | `requests.get/post(...)` without `timeout=` |\n| PY21 | HTTP request smuggling on outdated frameworks | CWE-444 | RV.1 | `gunicorn\u003c22.0.0` (CVE-2024-1135), `aiohttp\u003c3.9.2` (CVE-2024-23829) |\n| PY22 | Multipart resource exhaustion | CWE-400 | RV.1 | `python-multipart\u003c0.0.18` (CVE-2024-47874); FastAPI route without `max_part_size` |\n| PY23 | Weak hashing for passwords or auth tokens | CWE-327, CWE-328 | PW.5.1 | `hashlib.md5`, `hashlib.sha1` reachable from password / session-token paths |\n| PY24 | Missing TLS 1.2 floor | CWE-326 | PW.9 | `ssl.PROTOCOL_TLSv1`, `PROTOCOL_SSLv23` without `minimum_version` |\n| PY25 | Index pinning missing for PyPI consumption | CWE-829 | PW.4 | no `[[tool.uv.index]]` in `pyproject.toml`; no `--index-url` constraint in `requirements.txt` |\n| PY26 | Hash-unpinned installs | CWE-494, NIST SI-7 | PW.4 | `requirements.txt` without `--hash=` lines; missing `uv.lock`/`poetry.lock` |\n| PY27 | PyPI release without PEP 740 attestation | NIST SSDF PS.2.1 | PS.2 | release workflow uses static API token instead of `pypa/gh-action-pypi-publish@release/v1` (Trusted Publishers) |\n\n## Library substitution table\n\nWhen a finding fires, the proposal usually swaps the offending\nlibrary or call. The substitution table:\n\n| Bad | Good | Why |\n|-----|------|-----|\n| the unsafe-deserialization stdlib family | `json` if data is JSON-shaped, otherwise `msgspec` / `pydantic` | safe-by-default deserialization |\n| `yaml.load(...)` | `yaml.safe_load(...)` (or `ruamel.yaml.YAML(typ='safe')`) | rejects arbitrary tag construction |\n| `eval`, `exec` | `ast.literal_eval` for constants; otherwise refactor to a typed parser | no code path executes user input |\n| `random.{choice,token_bytes,...}` for security | `secrets.token_bytes/urlsafe`, `secrets.choice` | CSPRNG-backed |\n| `xml.etree.ElementTree` on untrusted input | `defusedxml.ElementTree` | XXE / billion-laughs hardened |\n| `urllib.request.urlopen` | `requests` (`timeout=`, `verify=True`) or `httpx` (defaults are safer) | timeout-by-default |\n| `tempfile.mktemp` | `tempfile.NamedTemporaryFile(delete=False)` | atomic creation |\n| `assert is_authorized()` | explicit `if not is_authorized(): raise PermissionError(...)` | survives `python -O` |\n| `hashlib.md5/sha1` for passwords | `argon2-cffi`, `bcrypt`, or `passlib` | KDF with cost factor |\n| static API tokens for PyPI | PyPI Trusted Publishers and sigstore attestation (PEP 740) | revocable, log-traceable, no shared secret |\n\n## Static-analyzer integration\n\nRun the canonical Python security tools and treat their findings\nas first-class harden findings:\n\n```bash\n# Bandit ruleset (PyCQA-maintained AST scanner)\nuv run bandit -r src/ -f json -o /tmp/harden-bandit.json\n\n# pip-audit on the lockfile (PyPA + Trail of Bits, OSV-backed)\nuv run pip-audit --lockfile uv.lock --format json > /tmp/harden-pipaudit.json\n\n# osv-scanner reads pyproject + lockfiles + Cargo.lock\nosv-scanner --format json . > /tmp/harden-osv.json\n\n# semgrep with the security-audit ruleset\nsemgrep --config=p/python --json --output=/tmp/harden-semgrep.json\n```\n\nFindings from these tools convert to the harden schema by joining\non file:line and severity. A bandit B301 finding (the unsafe\ndeserialization rule) becomes the same finding shape as the\ninternal PY01 detector, so the report does not double-count.\n\n## Frontier Python concerns (2025-2026)\n\nLoaded from `frontier-checks.md` for full coverage. Brief list:\n\n- PEP 740 sigstore attestations on PyPI (verify before install);\n see Trail of Bits' \"Attestations: a new generation of\n signatures on PyPI\" (Nov 2024).\n- Tarfile member filter (PEP 706) — `tarfile.data_filter` default\n in Python 3.12+; verify the codebase does not still pass\n `filter=None`.\n- pyproject.toml `[[tool.uv.index]]` priority pinning to defeat\n dependency confusion attacks.\n- LLM SDK prompt-injection patterns and MCP server hardening\n (CWE-1426; OWASP LLM Top 10 #01, #02).\n- ASGI middleware request smuggling (CVE-2024-23829 class).\n- Sandboxing application code: WASM (Pyodide), gVisor, nsjail.\n- Slopsquatting / package hallucination (arXiv 2406.10279):\n LLM-suggested non-existent packages later registered as\n malware. Mitigation: lockfile and `--require-hashes` and human\n review on every dep addition.\n\n## Output schema\n\nEach Python finding follows the schema in\n`modules/proposal-shape.md`. The detection-signal text uses safe\nplaceholders so the doc itself does not trip secret-scanners or\nthe project's security pre-commit hooks; the actual scanner emits\nthe literal pattern with file:line context in the report.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7917,"content_sha256":"4773bdb44b7e8b13bc19c98acf2aecb25b0f920fe7f2b7453d5c944837c915c7"},{"filename":"modules/rust-checks.md","content":"# Rust Hardening Checks\n\nDetectors for Rust codebases. The Rust ecosystem ships strong\ndefault safety; the harden skill verifies the discipline is\nactually applied and the supply chain is curated.\n\nFor a deep ownership/unsafe audit, the skill defers to\n`Skill(pensive:rust-review)`. This module focuses on the\nhardening posture (capability use, supply-chain hygiene,\nside-channel defense) and frontier 2025-2026 practices.\n\n## Detection ruleset\n\n| ID | Check | CWE / RustSec | NIST SSDF | Detection signal |\n|----|-------|---------------|-----------|------------------|\n| RS01 | Crate root lacks `#![forbid(unsafe_code)]` and does not declare audited unsafe | CWE-119 | PW.5 | `lib.rs`/`main.rs` without forbid; no `audit/unsafe.md` |\n| RS02 | Unsafe block without `// SAFETY:` comment | CWE-119 | PW.7 | `unsafe {` not preceded by `// SAFETY:` line |\n| RS03 | `unwrap()` / `expect()` on caller-supplied data | CWE-754 | PW.5 | `.unwrap()` after `parse()`, `from_str`, `serde::from_*` on external input |\n| RS04 | `panic!` reachable from request handler | CWE-754 | PW.5 | `panic!`, `unimplemented!`, `unreachable!` on user-input branches |\n| RS05 | `cargo audit` not wired to CI | RV.1 | RV.1 | no `cargo audit` step in `.github/workflows/*.yml` |\n| RS06 | `cargo deny` config missing or not enforced | RV.1 | PW.4 | no `deny.toml` or CI step missing |\n| RS07 | `cargo vet` audits stale / missing for new deps | RV.2 | PW.4 | `supply-chain/audits.toml` does not cover new entries in `Cargo.lock` |\n| RS08 | Comparing secrets with `==` | CWE-208 | PW.5 | `==` between `&[u8]` typed as token/secret/digest; should be `subtle::ConstantTimeEq` |\n| RS09 | Secrets not zeroized on drop | CWE-316 | PW.5 | secret-typed struct without `Zeroize`/`ZeroizeOnDrop` |\n| RS10 | Async cancellation un-safe | CWE-362 | PW.5 | `tokio::select!` arms with non-cancel-safe futures (e.g., `BufReader::read_to_end`) |\n| RS11 | `Mutex::lock().unwrap()` in hot path | CWE-754 | PW.5 | poisoned-lock unwrap reachable from public API |\n| RS12 | Source replacement to private registry without integrity pin | CWE-494 | PW.4 | `[source.crates-io]` `replace-with` without checksum |\n| RS13 | Git dependency without `rev=` | CWE-494 | PW.4 | `git = \"...\"` without `rev = \"...\"` (mutable target) |\n| RS14 | Build script (`build.rs`) reads files outside `OUT_DIR` | CWE-829 | PW.6 | `build.rs` opens path containing `..` |\n| RS15 | `serde(deny_unknown_fields)` missing on auth-bearing structs | CWE-1287 | PW.5 | struct deriving `Deserialize` for an auth/config payload without `#[serde(deny_unknown_fields)]` |\n| RS16 | Compiler hardening flags absent | CWE-1244 | PW.6 | `.cargo/config.toml` missing `RUSTFLAGS` for stack protection / CFI |\n| RS17 | `unsafe impl Send/Sync` without proof | CWE-362 | PW.7 | `unsafe impl (Send|Sync) for ...` without SAFETY comment |\n| RS18 | FFI without bounds annotation | CWE-787 | PW.5 | `extern \"C\"` function with `*const T` / `*mut T` arg with no length param |\n\n## Tooling integration\n\n```bash\n# Vulnerability scan against RustSec advisory DB\ncargo audit --json > /tmp/harden-cargo-audit.json\n\n# Policy enforcement (license, advisory, source, ban list)\ncargo deny check --format json 2>/tmp/harden-deny.json\n\n# Cryptographic-supply-chain audit\ncargo vet check 2>&1 | tee /tmp/harden-vet.log\n\n# Unsafe block inventory (third-party tool; requires install)\ncargo geiger --output-format json > /tmp/harden-geiger.json\n\n# Mutation testing (high-leverage; expensive)\ncargo mutants --in-diff origin/main..HEAD --no-times --json\n```\n\nThe harden report joins these on file:line and advisory ID.\n\n## Capability-style hardening (frontier 2025-2026)\n\n| From | To | Why |\n|------|-----|-----|\n| `std::fs` ambient access | `cap-std::fs::Dir` capability | filesystem ops require an explicit handle, not a path |\n| raw `socket`/`std::net` | `cap-std::net` | network endpoints are capabilities, not strings |\n| environment-driven config | `secrecy::SecretString` for secrets | wrapper prevents `Debug`/`Display` leaks |\n| ad-hoc retry loops | `tower::retry` with backoff and budget | bounded resource consumption (CWE-400) |\n\nThese are recommendations, not blocking findings — surface in\nthe report as MEDIUM advisories with the rationale in the\nproposal.\n\n## Concurrency hardening\n\n| Pattern | Replace with | Reason |\n|---------|--------------|--------|\n| naked `std::sync::Mutex` in hot path | `parking_lot::Mutex` (no poisoning, smaller, faster) | reduces unwrap-on-poison footguns |\n| ad-hoc `Arc\u003cMutex\u003cHashMap>>` | `dashmap::DashMap` | lock-free reads, sharded writes |\n| `tokio::sync::Mutex` held across `await` | `parking_lot::Mutex` for short critical sections | avoid tokio scheduler stalls |\n| `loom`-untested concurrent code | wire `cargo test --features loom` for lock-free types | model-checks all interleavings |\n\n## Compiler hardening flags\n\nIn `.cargo/config.toml`:\n\n```toml\n[target.'cfg(all())']\nrustflags = [\n # Stack-smashing protection\n \"-C\", \"force-frame-pointers=yes\",\n # Disable sources of UB\n \"-D\", \"warnings\",\n # Treat unsafe-op-without-unsafe-fn as error in 2024 edition\n \"-D\", \"unsafe_op_in_unsafe_fn\",\n]\n```\n\nFor sanitizer-instrumented test runs:\n\n```bash\nRUSTFLAGS=\"-Z sanitizer=address\" cargo +nightly test --target x86_64-unknown-linux-gnu\n```\n\n## Output schema\n\nSame as `python-checks.md`. Each Rust finding emits a single\nproposal with diff, blast radius, reversal plan, and expected\ntest. RustSec IDs go in the citation column when applicable.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5491,"content_sha256":"d04fd88e34575b6344e25c8a74d6f364866bf238fa7762a552ae318ed312d3cf"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Harden Codebase Skill","type":"text"}]},{"type":"paragraph","content":[{"text":"Active security hardening — scan the existing repository for vulnerabilities and forward-facing threats, then propose concrete remediations the user can approve, defer, or file.","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill is the engine behind ","type":"text"},{"text":"/harden","type":"text","marks":[{"type":"code_inline"}]},{"text":". It complements the Claude Code built-in ","type":"text"},{"text":"/security-review","type":"text","marks":[{"type":"code_inline"}]},{"text":" (which scans the pending diff) by sweeping the whole repository against citation-backed checks rather than line-level review of in-flight code.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When To Use","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Quarterly security-posture audits.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Before tagging a release that touches sensitive code paths.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"After a published advisory affects the language ecosystem.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"When onboarding a new repository and want a baseline.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"After integrating a new dependency or upstream service.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When NOT To Use","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pending-diff review on a single PR. Use ","type":"text"},{"text":"/security-review","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Architecture-level threat modeling. Use ","type":"text"},{"text":"attune:war-room","type":"text","marks":[{"type":"code_inline"}]},{"text":" with a security-focused panel.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cryptographic protocol review. The skill flags suspect crypto but does not propose protocol fixes (specialist work).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"One-off bug hunting. Use ","type":"text"},{"text":"pensive:bug-review","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Required TodoWrite Items","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:discovery","type":"text","marks":[{"type":"code_inline"}]},{"text":" — inventory languages, build files, hooks, CI workflows","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:scan-python","type":"text","marks":[{"type":"code_inline"}]},{"text":" — run python-checks.md detectors when Python is present","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:scan-rust","type":"text","marks":[{"type":"code_inline"}]},{"text":" — run rust-checks.md detectors when Rust is present","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:scan-cross-cutting","type":"text","marks":[{"type":"code_inline"}]},{"text":" — run cross-cutting.md detectors (deps, secrets, SBOM, CI)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:scan-frontier","type":"text","marks":[{"type":"code_inline"}]},{"text":" — run frontier-checks.md (PQC, LLM supply chain, sandboxing)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:nist-mapping","type":"text","marks":[{"type":"code_inline"}]},{"text":" — map findings to NIST SSDF practices","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:proposals","type":"text","marks":[{"type":"code_inline"}]},{"text":" — for each finding above the threshold, draft a concrete remediation per ","type":"text"},{"text":"modules/proposal-shape.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:approval-gate","type":"text","marks":[{"type":"code_inline"}]},{"text":" — present proposals to the user for apply / file / defer / reject","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:apply-and-validate","type":"text","marks":[{"type":"code_inline"}]},{"text":" — apply approved proposals as discrete commits, re-run gates, capture evidence","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"harden:report","type":"text","marks":[{"type":"code_inline"}]},{"text":" — write ","type":"text"},{"text":"reviews/harden-\u003cdate>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" and optionally post to Discussions","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Progressive Loading","type":"text"}]},{"type":"paragraph","content":[{"text":"Load modules based on what the discovery step finds.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Detected","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Load","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python files (","type":"text"},{"text":"*.py","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pyproject.toml","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"modules/python-checks.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rust files (","type":"text"},{"text":"*.rs","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"Cargo.toml","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"modules/rust-checks.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Any","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"modules/nist-controls.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (citation backbone)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Any","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"modules/cross-cutting.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (deps, secrets, CI)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"LLM SDK use (","type":"text"},{"text":"anthropic","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"openai","type":"text","marks":[{"type":"code_inline"}]},{"text":"), MCP server, post-quantum surface","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"modules/frontier-checks.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Any with proposals enabled","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"modules/proposal-shape.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"The module hub keeps the SKILL.md itself under the ","type":"text"},{"text":"estimated_tokens: 1100","type":"text","marks":[{"type":"code_inline"}]},{"text":" budget. Detail lives in the modules.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Core Workflow","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 1 — Discovery","type":"text"}]},{"type":"paragraph","content":[{"text":"Inventory the repo without modifying anything:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Languages and build files\nfind . -type f \\( -name '*.py' -o -name '*.rs' -o -name '*.sh' \\) \\\n | head -200 > /tmp/harden-langs.txt\n\n# Build manifests\nls pyproject.toml Cargo.toml package.json go.mod 2>/dev/null\n\n# CI workflows and pre-commit\nls .github/workflows/ .pre-commit-config.yaml 2>/dev/null\n\n# Hooks and Dockerfiles\nfind . -path ./node_modules -prune -o -type f \\\n \\( -name 'hooks.json' -o -name 'Dockerfile*' \\) -print","type":"text"}]},{"type":"paragraph","content":[{"text":"Dispatch ","type":"text"},{"text":"/discovery-prefilter","type":"text","marks":[{"type":"code_inline"}]},{"text":" if the repo has > 5000 source files to bound the scan.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 2 — Citation-backed scan","type":"text"}]},{"type":"paragraph","content":[{"text":"For each detected language, load the matching module and run its detector list. Each detector outputs findings with the schema defined in ","type":"text"},{"text":"modules/proposal-shape.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". The citation column is mandatory: a finding without a NIST/CWE reference is downgraded to \"advisory\" and not eligible for active proposal.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 3 — NIST mapping","type":"text"}]},{"type":"paragraph","content":[{"text":"Group findings by SSDF practice (PW.4, PW.8, RV.1, etc.) and CWE ID. The mapping table lives in ","type":"text"},{"text":"modules/nist-controls.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". The report's executive summary references SSDF practice coverage so the audit is comparable across runs.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 4 — Proposal generation","type":"text"}]},{"type":"paragraph","content":[{"text":"For each finding above the configured severity threshold, draft a concrete remediation per ","type":"text"},{"text":"modules/proposal-shape.md","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Specific files and lines touched","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Diff or config snippet (not \"consider doing X\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Blast-radius assessment via ","type":"text"},{"text":"pensive:blast-radius","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Reversal plan: how to revert if the change breaks behavior","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test that should pass after the change","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 5 — Approval gate","type":"text"}]},{"type":"paragraph","content":[{"text":"Present proposals one at a time via ","type":"text"},{"text":"AskUserQuestion","type":"text","marks":[{"type":"code_inline"}]},{"text":". Default options: ","type":"text"},{"text":"apply","type":"text","marks":[{"type":"strong"}]},{"text":", ","type":"text"},{"text":"file as issue","type":"text","marks":[{"type":"strong"}]},{"text":", ","type":"text"},{"text":"defer to backlog","type":"text","marks":[{"type":"strong"}]},{"text":", ","type":"text"},{"text":"reject","type":"text","marks":[{"type":"strong"}]},{"text":". Auto-apply is opt-in via the ","type":"text"},{"text":"--auto-apply","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag and respects a per-finding severity threshold.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 6 — Apply and validate","type":"text"}]},{"type":"paragraph","content":[{"text":"Apply each approved proposal as a discrete commit:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"git add \u003ctouched files>\ngit commit -m \"harden: \u003cfinding-id> \u003cone-line summary>\"","type":"text"}]},{"type":"paragraph","content":[{"text":"After each apply, re-run the project gates:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"make test --quiet && make lint && make type-check","type":"text"}]},{"type":"paragraph","content":[{"text":"If a gate fails, revert the commit (","type":"text"},{"text":"git revert HEAD --no-edit","type":"text","marks":[{"type":"code_inline"}]},{"text":") and downgrade the finding to \"needs human design.\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 7 — Report","type":"text"}]},{"type":"paragraph","content":[{"text":"Write ","type":"text"},{"text":"reviews/harden-\u003cdate>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" with:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Executive summary (SSDF practice coverage, CWE distribution)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Findings table grouped by severity","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Per-finding detail: detection signal, citation, proposal, status","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Disposition table (applied / filed / deferred / rejected)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Re-run instructions","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"If running inside a PR context, post the executive summary as a comment via ","type":"text"},{"text":"abstract:post_review_insights","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Severity Classification","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Severity","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Definition","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default disposition","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CRITICAL","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Active exploit path, RCE, credential leak","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"apply or file immediately","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HIGH","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Plausible exploit, missing defense-in-depth on attack surface","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"propose for apply","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MEDIUM","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Best-practice gap, hardening opportunity","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"propose for apply with ","type":"text"},{"text":"--auto-apply medium","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"LOW","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Style/documentation gap with security flavor","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"file as issue","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ADVISORY","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pattern detected without exploit narrative","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"report only","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Output Format","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"# Hardening Report — \u003cdate>\n\n## Executive Summary\n\n- Codebase: \u003crepo> @ \u003csha>\n- Languages scanned: Python (X files), Rust (Y files)\n- NIST SSDF practices covered: PW.4, PW.7, PW.8, RV.1, RV.2\n- CWE Top 25 hits: \u003ccount> across \u003cdistinct CWEs>\n- Disposition: \u003cN> applied, \u003cN> filed, \u003cN> deferred, \u003cN> rejected\n\n## Findings\n\n| ID | Severity | Citation | File:Line | Disposition |\n|----|----------|----------|-----------|-------------|\n| H1 | CRITICAL | CWE-502, NIST SSDF PW.7 | `src/x.py:45` | applied (commit abc123) |\n| H2 | HIGH | CWE-89, NIST SSDF PW.4 | `src/y.py:120` | filed (#456) |\n\n## Per-finding detail\n\n### H1 — Unsafe deserialization\n\n**Citation:** CWE-502 (Deserialization of Untrusted Data),\nNIST SSDF PW.7 (Review and analyze human-readable code).\n\n**Detection signal:**\n- File: `src/x.py:45`\n- Pattern: \u003cmodule>.loads(user_supplied_input)\n- Reachability: untrusted, comes from request body\n\n**Proposal:** ...\n\n**Blast radius:** ...\n\n**Reversal plan:** ...","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Safety Rails","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never apply without approval.","type":"text","marks":[{"type":"strong"}]},{"text":" Even with ","type":"text"},{"text":"--auto-apply","type":"text","marks":[{"type":"code_inline"}]},{"text":", CRITICAL findings always prompt.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"One finding per commit.","type":"text","marks":[{"type":"strong"}]},{"text":" Reversals are per-finding, not per-batch.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Re-run gates after each apply.","type":"text","marks":[{"type":"strong"}]},{"text":" A gate failure reverts the commit and downgrades the finding.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Citation is mandatory.","type":"text","marks":[{"type":"strong"}]},{"text":" Findings without a NIST/CWE/RustSec reference are advisory only and skip the apply phase.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Read-only on first run.","type":"text","marks":[{"type":"strong"}]},{"text":" First invocation defaults to ","type":"text"},{"text":"--report-only","type":"text","marks":[{"type":"code_inline"}]},{"text":" until the user has reviewed at least one report and explicitly opts into proposals.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Integration","type":"text"}]},{"type":"paragraph","content":[{"text":"The skill composes (rather than re-implements):","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pensive:rust-review","type":"text","marks":[{"type":"code_inline"}]},{"text":" — full Rust audit when Rust is present","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pensive:bug-review","type":"text","marks":[{"type":"code_inline"}]},{"text":" — bug-hunting backbone","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pensive:safety-critical-patterns","type":"text","marks":[{"type":"code_inline"}]},{"text":" — NASA Power-of-10 adapted","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pensive:tiered-audit","type":"text","marks":[{"type":"code_inline"}]},{"text":" — three-tier discipline (","type":"text"},{"text":"--tier 1/2/3","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pensive:blast-radius","type":"text","marks":[{"type":"code_inline"}]},{"text":" — change-impact assessment for proposals","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"leyline:supply-chain-advisory","type":"text","marks":[{"type":"code_inline"}]},{"text":" — dependency posture","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"leyline:authentication-patterns","type":"text","marks":[{"type":"code_inline"}]},{"text":" — auth/credential review","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"leyline:content-sanitization","type":"text","marks":[{"type":"code_inline"}]},{"text":" — input handling","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"abstract:hook-authoring","type":"text","marks":[{"type":"code_inline"}]},{"text":" — hook-event security","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"imbue:proof-of-work","type":"text","marks":[{"type":"code_inline"}]},{"text":" — evidence discipline for findings","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Exit Criteria","type":"text"}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Discovery output lists every language and build manifest detected in the repo.","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Each finding carries a CWE or NIST SSDF citation; the report executive summary lists the SSDF practice coverage.","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Each finding above the severity threshold has a concrete proposal (file, diff or config snippet, blast radius, reversal plan, expected-passing test).","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"No proposal was applied without explicit user approval (or without an ","type":"text"},{"text":"--auto-apply","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag covering its severity).","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Each applied proposal is its own commit, reversal-friendly.","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"After every apply, the project gates were re-run; any gate failure reverted the commit and downgraded the finding.","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"reviews/harden-\u003cdate>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" exists and lists every finding with a disposition (applied / filed / deferred / rejected / advisory).","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"harden","tags":["security","hardening","nist","supply-chain","python","rust","cwe"],"globs":"**/*.{py,rs,toml,yaml,yml,sh}","tools":[],"author":"@skillopedia","source":{"stars":298,"repo_name":"claude-night-market","origin_url":"https://github.com/athola/claude-night-market/blob/HEAD/plugins/pensive/skills/harden/SKILL.md","repo_owner":"athola","body_sha256":"112ffacee27aba2ff30412ccef38045b3f8c08d6c52c057f8de25c10255806a6","cluster_key":"749ee71b60041c6bd96b60fc8b4fe7c8df51387ec7c7d87e60f6a24b00975b59","clean_bundle":{"format":"clean-skill-bundle-v1","source":"athola/claude-night-market/plugins/pensive/skills/harden/SKILL.md","attachments":[{"id":"7f71bfd5-48dd-5b38-9d69-c8203172e9a7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7f71bfd5-48dd-5b38-9d69-c8203172e9a7/attachment.md","path":"modules/cross-cutting.md","size":5415,"sha256":"15db915340fc70971fb4f66daeed35cd68cfba093abff3d8ab7b5d0f4d3026a5","contentType":"text/markdown; charset=utf-8"},{"id":"bae2bc7c-7838-590c-bc11-6d530815d822","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bae2bc7c-7838-590c-bc11-6d530815d822/attachment.md","path":"modules/frontier-checks.md","size":5056,"sha256":"f2a1abe0f2c6d9c757c5beb00f78030dc66a0d7880c2efa1677794548ced7b98","contentType":"text/markdown; charset=utf-8"},{"id":"0d48ea99-2810-52c6-abee-84c5a5c84f8c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0d48ea99-2810-52c6-abee-84c5a5c84f8c/attachment.md","path":"modules/nist-controls.md","size":4262,"sha256":"4657468ff017eee27367e746f2c48cb8a42275504e018cda3ed996c6ac20a13a","contentType":"text/markdown; charset=utf-8"},{"id":"44eb0460-df22-5ae4-94f0-5160bc532659","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/44eb0460-df22-5ae4-94f0-5160bc532659/attachment.md","path":"modules/proposal-shape.md","size":5761,"sha256":"62ade6cecdceceeabbcbb318ac40eb5f3ea66e380ee769e78fc787fedbdfdc66","contentType":"text/markdown; charset=utf-8"},{"id":"94a9ec2c-d7df-5084-b8c0-963660a21e8d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/94a9ec2c-d7df-5084-b8c0-963660a21e8d/attachment.md","path":"modules/python-checks.md","size":7917,"sha256":"4773bdb44b7e8b13bc19c98acf2aecb25b0f920fe7f2b7453d5c944837c915c7","contentType":"text/markdown; charset=utf-8"},{"id":"d5ba4856-8e26-56df-8ef0-0f1f5fd54188","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d5ba4856-8e26-56df-8ef0-0f1f5fd54188/attachment.md","path":"modules/rust-checks.md","size":5491,"sha256":"d04fd88e34575b6344e25c8a74d6f364866bf238fa7762a552ae318ed312d3cf","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"e8c3edd3b27c704a7a749824db02e96ee850577c14c9126f47974ddbabf9ab0c","attachment_count":6,"text_attachments":6,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"plugins/pensive/skills/harden/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"security","category_label":"Security"},"exact_dupes_collapsed_into_this":0},"modules":["modules/nist-controls.md","modules/python-checks.md","modules/rust-checks.md","modules/cross-cutting.md","modules/frontier-checks.md","modules/proposal-shape.md"],"version":"v1","category":"security","provides":{"security":["vuln-detection","hardening-posture"],"governance":["hardening-report","remediation-proposal"]},"complexity":"advanced","import_tag":"clean-skills-v1","model_hint":"deep","alwaysApply":false,"description":"Applies NIST/CWE security hardening to Python and Rust code. Use when auditing code for vulnerabilities or proposing concrete security remediations.","dependencies":["pensive:safety-critical-patterns","pensive:rust-review","pensive:bug-review","pensive:tiered-audit","pensive:blast-radius","leyline:supply-chain-advisory","leyline:authentication-patterns","leyline:content-sanitization","abstract:hook-authoring","imbue:proof-of-work"],"usage_patterns":["security-hardening","quarterly-posture-audit","pre-release-security-gate"],"estimated_tokens":1100,"progressive_loading":true}},"renderedAt":1782982410815}

Harden Codebase Skill Active security hardening — scan the existing repository for vulnerabilities and forward-facing threats, then propose concrete remediations the user can approve, defer, or file. This skill is the engine behind . It complements the Claude Code built-in (which scans the pending diff) by sweeping the whole repository against citation-backed checks rather than line-level review of in-flight code. When To Use - Quarterly security-posture audits. - Before tagging a release that touches sensitive code paths. - After a published advisory affects the language ecosystem. - When on…