Skip to content

Security - caveman-savings

Threat model

Both scripts run locally, unattended, with the operator's own privileges, against the operator's own ~/.claude configuration directory. There is no network listener, no outbound network call, no subprocess execution of untrusted input, and no credential of any kind read, written, or required. The realistic risk surface is limited to:

  • accidental data loss in ~/.claude/CLAUDE.md or ~/.claude/settings.json from a bad write (mitigated: idempotent read-modify-write with a .bak backup before every settings.json write, and in-place marker-fenced block replacement for CLAUDE.md);
  • accidental cross-project backup collision in Migrate-CavemanBackups.ps1's attribution logic (mitigated: ambiguous cases are left untouched and warned about rather than guessed).

Secrets handling

There are no secrets in this repository, by design - neither script needs to authenticate to anything. The hard secret-grep gate (council_[a-z0-9]{20,}|Bearer [A-Za-z0-9._-]{12,}|AKIA[0-9A-Z]{16}|sk-[A-Za-z0-9]{20,}|gh[pousr]_[A-Za-z0-9]{20,}|xox[baprs]-[A-Za-z0-9-]{10,}|-----BEGIN [A-Z ]*PRIVATE KEY-----) was run over the full working tree (scripts/, tests/, docs/, this file) before every commit and returned no matches. A Pester test (No hardcoded secrets in tests/CavemanSavings.Tests.ps1) also asserts neither script contains a bearer-token, sk-, AKIA, or PEM private-key literal, so a future accidental addition fails CI, not just a pre-commit grep.

Scan results summary

Scan Result
Secret grep (hard gate) Clean - no matches in scripts/, tests/, or docs/
Codex security review (codex exec over the repo) No secrets/RCE found. 4 CI-template findings (below); see docs/MAKING-OF.md chapter 1 for the verbatim verdict
Semgrep (semgrep scan --config auto --error ., via Docker, CI security job) Runs on every push/PR

Codex findings (none block the ship gate - no secret or RCE finding)

  1. HIGH - ci.yml runs pull_request on a non-ephemeral self-hosted runner. This is the house-standard CI template (identical in house-council-client), mitigated by the repo being private with house-member-only contributors, as noted in the workflow's own supply-chain comment block. Accepted at the fleet level, not specific to this repo.
  2. MEDIUM - docker run semgrep/semgrep uses a floating :latest tag rather than a digest pin. Same as the pilot template. Left as-is to match the house CI template exactly; worth revisiting fleet-wide (not per-repo) if the org migration adds an image-mirroring step.
  3. MEDIUM - the Pester bootstrap step trusts PSGallery and installs with -SkipPublisherCheck. Same as the pilot template - CI-bootstrap-only, does not affect the shipped scripts.
  4. LOW - Apply-CavemanSavings.ps1 discovers compress.py under the (mutable) local plugin cache and runs the first python on PATH. Local-machine-only, no network involved; an operator with a poisoned plugin cache or PATH already has arbitrary code execution on their own machine regardless of this script. Tracked as a backlog item in docs/BOARD.md (make the compress command injectable/overridable) rather than fixed here.

Supply chain

  • .github/workflows/ci.yml pins actions/checkout to a full commit SHA (11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2), not a mutable tag.
  • No third-party PowerShell modules are required to run either script - only Pester (a well-known, widely-vetted test framework) is required to test them, and only in CI/dev.
  • Semgrep runs via the official semgrep/semgrep Docker image (no native Windows binary exists), so the CI runner never installs an unaudited pip package for this.