arbiterforge/codearbiter-ca-secret-handling
The secret-source gate. Routed to when changed code reads, writes, or passes a secret — API key, token, password, connection string, signing key, certificate, or any value that grants access. Validates that every secret comes from the approved store and never lands in source, log, test fixture, error response, image, or LLM prompt. The auth-crypto-reviewer agent is dispatched as the reviewer.
npx skills add https://github.com/arbiterForge/codeArbiter --skill secret-handling
The secret-source gate. Routed to when changed code reads, writes, generates, stores, or passes a secret. If a value's secret status is uncertain, treat it as a secret.
Read these, or STOP and surface the gap — never guess the policy:
${CLAUDE_PROJECT_DIR}/.codearbiter/security-controls.md — the approved secret store, the access method (IAM role, workload identity, service-account token — never long-lived static keys), and any required reference format. If this file is unreadable, BLOCK; do not infer the store.Scan the changed code for secret-bearing names: password, secret, token, key, credential, api_key, apikey, private, cert, passphrase. For each match, record its source (where the value originates) and every sink (where it flows). No candidate may remain unclassified.
Gate: every candidate secret is listed with its source and sinks.
Each secret MUST originate from the approved store in security-controls.md, accessed via the approved method. The following sources BLOCK unconditionally:
process.env or .env for a secret value — these are for non-sensitive config only (ports, log levels). .env files MUST be gitignored and secrets-scanned on every PR.security-controls.md.Stakes: a hardcoded or unapproved-source secret ships to every clone, every CI log, and the
history; rotation is the only fix once it lands. State that when you block, not just "unapproved
source." A genuine catch the user then rotates earns exactly one warm sentence at the close (per
the orchestrator register), never on a clean pass.
Gate: every secret is sourced from the approved store via the approved access method.
Trace each secret to all sinks. These are prohibited regardless of project, with no log-redaction excuse:
security-controls.md requires. A migration adding a reference column without a format check constraint BLOCKs.Secrets MUST NOT outlive the request that uses them — no module-level variable, no instance field, no cross-request cache holding a secret value.
Dispatch the auth-crypto-reviewer agent (${CLAUDE_PLUGIN_ROOT}/agents/auth-crypto-reviewer.md) to confirm these findings against security-controls.md.
Gate: no secret reaches a prohibited sink and no secret persists beyond its request.
On pass — record the gate: follow ${CLAUDE_PLUGIN_ROOT}/includes/security-gate-record.md (the shared record mechanism). For this gate the relevant commit hook is H-10b (secrets). On any BLOCK, do NOT record the pass.
Out-of-scope finding: do not act on it and do not author an ADR (ADRs are user-attributed, via /adr only). Mark it inline with [NEEDS-TRIAGE]; never silently drop it.
security-controls.md for the approved store before Phase 2 — BLOCK if it cannot be read.process.env, a .env file, or any unapproved store.security-gate-passed marker (via hooks/security-pass.py) ONLY when the gate genuinely passes — the marker is what unblocks the commit (hook H-10b), so a premature or unconditional recording defeats the gate.Take arbiterforge/codearbiter-ca-secret-handling from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.