From e2d0a88d61764c14e2d1f4544a5960d314d1133b Mon Sep 17 00:00:00 2001 From: andreycpu Date: Fri, 17 Apr 2026 12:30:21 -0700 Subject: [PATCH] feat(cso): add --fix flag with 9 provably safe auto-fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds /cso --fix which runs the full audit then applies a curated set of fixes where the correct change is deterministic and the risk of breakage is near-zero. Fix catalog: - FIX-01: .gitignore secret hardening (.env, *.pem, *.key, etc.) - FIX-02: Create .gitleaks.toml baseline if absent - FIX-03: npm audit fix (non-breaking patches only, no --force) - FIX-04: rejectUnauthorized: false → true (Node.js TLS bypass) - FIX-05: verify=False → True (Python requests TLS bypass) - FIX-06: InsecureSkipVerify: true → false (Go TLS bypass) - FIX-07: httpOnly: false → true on session cookies - FIX-08: secure: false → true on session cookies - FIX-09: DEBUG=true → false in production env files Each fix includes an explicit "Safe because" rationale. --fix is combinable with any existing scope flag (--code, --infra, --diff, etc.) and runs as Phase 15 after the report is complete. No changes to existing audit phases. --- cso/SKILL.md | 107 +++++++++++++++++++++++++++++++++++++++++++++- cso/SKILL.md.tmpl | 107 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 210 insertions(+), 4 deletions(-) diff --git a/cso/SKILL.md b/cso/SKILL.md index 570742073..fead27c41 100644 --- a/cso/SKILL.md +++ b/cso/SKILL.md @@ -16,6 +16,7 @@ allowed-tools: - Grep - Glob - Write + - Edit - Agent - WebSearch - AskUserQuestion @@ -564,7 +565,7 @@ You are a **Chief Security Officer** who has led incident response on real breac The real attack surface isn't your code — it's your dependencies. Most teams audit their own app but forget: exposed env vars in CI logs, stale API keys in git history, forgotten staging servers with prod DB access, and third-party webhooks that accept anything. Start there, not at the code level. -You do NOT make code changes. You produce a **Security Posture Report** with concrete findings, severity ratings, and remediation plans. +In audit-only mode, you do NOT make code changes. You produce a **Security Posture Report** with concrete findings, severity ratings, and remediation plans. With `--fix`, you apply a curated set of provably safe auto-fixes after the audit completes. ## User-invocable When the user types `/cso`, run this skill. @@ -579,6 +580,7 @@ When the user types `/cso`, run this skill. - `/cso --supply-chain` — dependency audit only (Phases 0, 3, 12-14) - `/cso --owasp` — OWASP Top 10 only (Phases 0, 9, 12-14) - `/cso --scope auth` — focused audit on a specific domain +- `/cso --fix` — run full audit, then auto-apply provably safe fixes (combinable with any scope flag) ## Mode Resolution @@ -588,7 +590,8 @@ When the user types `/cso`, run this skill. 4. `--diff` is combinable with ANY scope flag AND with `--comprehensive`. 5. When `--diff` is active, each phase constrains scanning to files/configs changed on the current branch vs the base branch. For git history scanning (Phase 2), `--diff` limits to commits on the current branch only. 6. Phases 0, 1, 12, 13, 14 ALWAYS run regardless of scope flag. -7. If WebSearch is unavailable, skip checks that require it and note: "WebSearch unavailable — proceeding with local-only analysis." +7. `--fix` is combinable with ANY scope flag and with `--comprehensive` or `--diff`. When `--fix` is active, run Phase 15 after Phase 14. +8. If WebSearch is unavailable, skip checks that require it and note: "WebSearch unavailable — proceeding with local-only analysis." ## Important: Use the Grep tool for all code searches @@ -1195,6 +1198,106 @@ Write findings to `.gstack/security-reports/{date}-{HHMMSS}.json` using this sch If `.gstack/` is not in `.gitignore`, note it in findings — security reports should stay local. +### Phase 15: Auto-Fix Engine (only runs with `--fix`) + +This phase applies a curated set of provably safe fixes — patterns where the correct change is deterministic, the risk of breakage is near-zero, and the security gain is concrete. No business logic involved. No guessing. + +**Fix catalog — 9 patterns:** + +**FIX-01: .gitignore secret hardening** +Scan `.gitignore` for missing entries. Add if absent: +``` +.env +.env.* +!.env.example +*.pem +*.key +*.p12 +*.pfx +``` +Safe because: additive only. Never removes existing entries. + +**FIX-02: Missing `.gitleaks.toml`** +If no `.gitleaks.toml` exists, create one with a baseline config that extends the default ruleset: +```toml +title = "gitleaks config" + +[extend] +useDefault = true + +[[allowlists]] +description = "test fixtures" +paths = ['''test''', '''spec''', '''fixtures''', '''__tests__'''] +``` +Safe because: additive. Does not block any existing workflow unless gitleaks is already running (in which case the file was already needed). + +**FIX-03: npm audit fix (non-breaking patches only)** +```bash +npm audit fix +``` +Run only if `package.json` exists and there are audit findings. Do NOT run `npm audit fix --force` (that allows major version bumps). Only patches and minor upgrades. +Safe because: respects semver constraints in `package.json`. Never changes APIs. + +**FIX-04: Node.js TLS bypass (`rejectUnauthorized: false`)** +Find all occurrences with the Grep tool: pattern `rejectUnauthorized\s*:\s*false`. +For each match: read the file, verify it's not in a test file or commented out, then use Edit to flip to `true`. +Safe because: single token flip. A `false` here disables TLS cert verification entirely — this is almost always a copy-paste mistake, never intentional in production code. If it's intentional (self-signed cert in dev), the developer will see the fix in the diff and revert. + +**FIX-05: Python requests TLS bypass (`verify=False`)** +Find all occurrences: pattern `requests\.(get|post|put|patch|delete|request)\(.*verify=False`. +For each match: read the file, verify it's production code (not a test), use Edit to change `verify=False` to `verify=True`. +Safe because: same reasoning as FIX-04. + +**FIX-06: Go TLS bypass (`InsecureSkipVerify: true`)** +Find all occurrences: pattern `InsecureSkipVerify\s*:\s*true`. +For each match: read the file, verify it's not test infrastructure, use Edit to flip to `false`. +Safe because: same reasoning as FIX-04. + +**FIX-07: Insecure cookie `httpOnly: false`** +Find all occurrences: pattern `httpOnly\s*:\s*false` in JS/TS files. +For each match: flip to `true`. This prevents JavaScript from reading the cookie — the correct default for session cookies. +Safe because: `httpOnly: true` never breaks server-side code. It only blocks `document.cookie` access, which should never be needed for session/auth cookies. + +**FIX-08: Insecure cookie `secure: false`** +Find all occurrences: pattern `secure\s*:\s*false` in cookie configuration contexts (near `httpOnly`, `sameSite`, `maxAge`). +For each match: flip to `true`. +Safe because: if you're in production (the only place this matters), you're on HTTPS. If you're in dev, you likely have `NODE_ENV` checks separating the config already. Single flag flip. + +**FIX-09: `DEBUG=true` in production env files** +Search for files named `.env.production`, `.env.prod`, `production.env` containing `DEBUG=true` or `DEBUG=1`. +For each match: flip to `DEBUG=false` or `DEBUG=0`. +Safe because: debug mode in production leaks stack traces and internal state. Flipping this off is never a behavioral regression — it only removes information leakage. + +--- + +**Fix execution protocol:** + +For each applicable fix: +1. Show the user what will change (file, line, before/after). +2. Apply the fix using the Edit tool (for file edits) or Bash (for commands like `npm install`). +3. Mark the fix as applied in the summary. + +Do NOT ask for confirmation before each individual fix — the user invoked `--fix` knowing fixes would be applied. Do ask via AskUserQuestion if a fix is ambiguous (e.g., multiple Express entry points, unclear which is production config). + +**Fix summary table:** + +After applying all fixes, print: + +``` +AUTO-FIX SUMMARY +════════════════ +Fix Applied Finding +─── ─────── ─────── +FIX-01 YES .gitignore: added .env, *.pem, *.key patterns +FIX-02 NO .gitleaks.toml already exists +FIX-03 YES npm audit fix: 3 vulnerabilities patched +FIX-04 YES api/http-client.ts:47: rejectUnauthorized false → true +FIX-07 YES lib/session.ts:12: httpOnly false → true +FIX-09 YES .env.production:3: DEBUG=true → DEBUG=false +``` + +If no fixes applied: "No safe auto-fixes found for this codebase. Review findings in Phase 13 for manual remediation steps." + ## Capture Learnings If you discovered a non-obvious pattern, pitfall, or architectural insight during diff --git a/cso/SKILL.md.tmpl b/cso/SKILL.md.tmpl index 2f849ee00..b94a75f51 100644 --- a/cso/SKILL.md.tmpl +++ b/cso/SKILL.md.tmpl @@ -22,6 +22,7 @@ allowed-tools: - Grep - Glob - Write + - Edit - Agent - WebSearch - AskUserQuestion @@ -41,7 +42,7 @@ You are a **Chief Security Officer** who has led incident response on real breac The real attack surface isn't your code — it's your dependencies. Most teams audit their own app but forget: exposed env vars in CI logs, stale API keys in git history, forgotten staging servers with prod DB access, and third-party webhooks that accept anything. Start there, not at the code level. -You do NOT make code changes. You produce a **Security Posture Report** with concrete findings, severity ratings, and remediation plans. +In audit-only mode, you do NOT make code changes. You produce a **Security Posture Report** with concrete findings, severity ratings, and remediation plans. With `--fix`, you apply a curated set of provably safe auto-fixes after the audit completes. ## User-invocable When the user types `/cso`, run this skill. @@ -56,6 +57,7 @@ When the user types `/cso`, run this skill. - `/cso --supply-chain` — dependency audit only (Phases 0, 3, 12-14) - `/cso --owasp` — OWASP Top 10 only (Phases 0, 9, 12-14) - `/cso --scope auth` — focused audit on a specific domain +- `/cso --fix` — run full audit, then auto-apply provably safe fixes (combinable with any scope flag) ## Mode Resolution @@ -65,7 +67,8 @@ When the user types `/cso`, run this skill. 4. `--diff` is combinable with ANY scope flag AND with `--comprehensive`. 5. When `--diff` is active, each phase constrains scanning to files/configs changed on the current branch vs the base branch. For git history scanning (Phase 2), `--diff` limits to commits on the current branch only. 6. Phases 0, 1, 12, 13, 14 ALWAYS run regardless of scope flag. -7. If WebSearch is unavailable, skip checks that require it and note: "WebSearch unavailable — proceeding with local-only analysis." +7. `--fix` is combinable with ANY scope flag and with `--comprehensive` or `--diff`. When `--fix` is active, run Phase 15 after Phase 14. +8. If WebSearch is unavailable, skip checks that require it and note: "WebSearch unavailable — proceeding with local-only analysis." ## Important: Use the Grep tool for all code searches @@ -613,6 +616,106 @@ Write findings to `.gstack/security-reports/{date}-{HHMMSS}.json` using this sch If `.gstack/` is not in `.gitignore`, note it in findings — security reports should stay local. +### Phase 15: Auto-Fix Engine (only runs with `--fix`) + +This phase applies a curated set of provably safe fixes — patterns where the correct change is deterministic, the risk of breakage is near-zero, and the security gain is concrete. No business logic involved. No guessing. + +**Fix catalog — 9 patterns:** + +**FIX-01: .gitignore secret hardening** +Scan `.gitignore` for missing entries. Add if absent: +``` +.env +.env.* +!.env.example +*.pem +*.key +*.p12 +*.pfx +``` +Safe because: additive only. Never removes existing entries. + +**FIX-02: Missing `.gitleaks.toml`** +If no `.gitleaks.toml` exists, create one with a baseline config that extends the default ruleset: +```toml +title = "gitleaks config" + +[extend] +useDefault = true + +[[allowlists]] +description = "test fixtures" +paths = ['''test''', '''spec''', '''fixtures''', '''__tests__'''] +``` +Safe because: additive. Does not block any existing workflow unless gitleaks is already running (in which case the file was already needed). + +**FIX-03: npm audit fix (non-breaking patches only)** +```bash +npm audit fix +``` +Run only if `package.json` exists and there are audit findings. Do NOT run `npm audit fix --force` (that allows major version bumps). Only patches and minor upgrades. +Safe because: respects semver constraints in `package.json`. Never changes APIs. + +**FIX-04: Node.js TLS bypass (`rejectUnauthorized: false`)** +Find all occurrences with the Grep tool: pattern `rejectUnauthorized\s*:\s*false`. +For each match: read the file, verify it's not in a test file or commented out, then use Edit to flip to `true`. +Safe because: single token flip. A `false` here disables TLS cert verification entirely — this is almost always a copy-paste mistake, never intentional in production code. If it's intentional (self-signed cert in dev), the developer will see the fix in the diff and revert. + +**FIX-05: Python requests TLS bypass (`verify=False`)** +Find all occurrences: pattern `requests\.(get|post|put|patch|delete|request)\(.*verify=False`. +For each match: read the file, verify it's production code (not a test), use Edit to change `verify=False` to `verify=True`. +Safe because: same reasoning as FIX-04. + +**FIX-06: Go TLS bypass (`InsecureSkipVerify: true`)** +Find all occurrences: pattern `InsecureSkipVerify\s*:\s*true`. +For each match: read the file, verify it's not test infrastructure, use Edit to flip to `false`. +Safe because: same reasoning as FIX-04. + +**FIX-07: Insecure cookie `httpOnly: false`** +Find all occurrences: pattern `httpOnly\s*:\s*false` in JS/TS files. +For each match: flip to `true`. This prevents JavaScript from reading the cookie — the correct default for session cookies. +Safe because: `httpOnly: true` never breaks server-side code. It only blocks `document.cookie` access, which should never be needed for session/auth cookies. + +**FIX-08: Insecure cookie `secure: false`** +Find all occurrences: pattern `secure\s*:\s*false` in cookie configuration contexts (near `httpOnly`, `sameSite`, `maxAge`). +For each match: flip to `true`. +Safe because: if you're in production (the only place this matters), you're on HTTPS. If you're in dev, you likely have `NODE_ENV` checks separating the config already. Single flag flip. + +**FIX-09: `DEBUG=true` in production env files** +Search for files named `.env.production`, `.env.prod`, `production.env` containing `DEBUG=true` or `DEBUG=1`. +For each match: flip to `DEBUG=false` or `DEBUG=0`. +Safe because: debug mode in production leaks stack traces and internal state. Flipping this off is never a behavioral regression — it only removes information leakage. + +--- + +**Fix execution protocol:** + +For each applicable fix: +1. Show the user what will change (file, line, before/after). +2. Apply the fix using the Edit tool (for file edits) or Bash (for commands like `npm install`). +3. Mark the fix as applied in the summary. + +Do NOT ask for confirmation before each individual fix — the user invoked `--fix` knowing fixes would be applied. Do ask via AskUserQuestion if a fix is ambiguous (e.g., multiple Express entry points, unclear which is production config). + +**Fix summary table:** + +After applying all fixes, print: + +``` +AUTO-FIX SUMMARY +════════════════ +Fix Applied Finding +─── ─────── ─────── +FIX-01 YES .gitignore: added .env, *.pem, *.key patterns +FIX-02 NO .gitleaks.toml already exists +FIX-03 YES npm audit fix: 3 vulnerabilities patched +FIX-04 YES api/http-client.ts:47: rejectUnauthorized false → true +FIX-07 YES lib/session.ts:12: httpOnly false → true +FIX-09 YES .env.production:3: DEBUG=true → DEBUG=false +``` + +If no fixes applied: "No safe auto-fixes found for this codebase. Review findings in Phase 13 for manual remediation steps." + {{LEARNINGS_LOG}} {{GBRAIN_SAVE_RESULTS}}