feat: carve cso into skeleton + on-demand section (security-safe)

Scope-dependent audit Phases 2-11 move to sections/audit-phases.md. Mode
dispatch (## Arguments, ## Mode Resolution), always-run Phases 0/1, and the
Phase 12 false-positive-filtering exceptions stay ALWAYS-LOADED in the
skeleton. Skeleton 79,383 -> 65,117 B (-18%); union preserved.

Adds a cso CARVE_GUARDS entry with an earliest-use invariant (mustPrecedeStop):
mode dispatch must appear before any STOP-Read, so a directive that decides
which sections to read can't be stranded behind the STOP that reads them
(codex outside-voice #6). carve-guard-checks gains the mustPrecedeStop check.
parity moves cso monolith -> generated carved entry. cso-preserved.test.ts
strengthened: phrases checked against the union, plus an always-loaded
contract on the skeleton (dispatch + FP-filtering, codex #5).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-06-07 17:57:50 -07:00
parent 672cbf6f30
commit 12ab68dda0
9 changed files with 662 additions and 558 deletions
+14 -249
View File
@@ -746,6 +746,18 @@ When the user types `/cso`, run this skill.
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."
---
## Section index — Read each section when its situation applies
This skill is a decision-tree skeleton. The steps below point to on-demand
sections. Read a section in full before doing its step; do not work from memory.
| When | Read this section |
|------|-------------------|
| running the scope-dependent audit phases (Phases 2-11) selected by the resolved mode, after the Phase 0 stack detection and Phase 1 attack-surface census | `sections/audit-phases.md` |
---
## Important: Use the Grep tool for all code searches
The bash blocks throughout this skill show WHAT patterns to search for, not HOW to run them. Use Claude Code's Grep tool (which handles permissions and access correctly) rather than raw bash grep. The bash blocks are illustrative examples — do NOT copy-paste them into a terminal. Do NOT use `| head` to truncate results.
@@ -870,255 +882,8 @@ INFRASTRUCTURE SURFACE
Secret management: [env vars | KMS | vault | unknown]
```
### Phase 2: Secrets Archaeology
Scan git history for leaked credentials, check tracked `.env` files, find CI configs with inline secrets.
**Canonical pattern catalog.** The HIGH-tier credential prefixes the archaeology
greps below target (AKIA, ghp_, sk-ant-, sk_live_, xoxb-, `-----BEGIN ... PRIVATE
KEY-----`, etc.) are the same set `/spec`'s in-flight redaction blocks on. The full
3-tier taxonomy (HIGH credentials, MEDIUM PII/legal/internal, LOW) is generated from
and lives in `lib/redact-patterns.ts` — the single source of truth shared by the
`gstack-redact` engine, `/spec`, `/ship`, and the `/document-*` skills.
**Git history — known secret prefixes:**
```bash
git log -p --all -S "AKIA" --diff-filter=A -- "*.env" "*.yml" "*.yaml" "*.json" "*.toml" 2>/dev/null
git log -p --all -S "sk-" --diff-filter=A -- "*.env" "*.yml" "*.json" "*.ts" "*.js" "*.py" 2>/dev/null
git log -p --all -G "ghp_|gho_|github_pat_" 2>/dev/null
git log -p --all -G "xoxb-|xoxp-|xapp-" 2>/dev/null
git log -p --all -G "password|secret|token|api_key" -- "*.env" "*.yml" "*.json" "*.conf" 2>/dev/null
```
**.env files tracked by git:**
```bash
git ls-files '*.env' '.env.*' 2>/dev/null | grep -v '.example\|.sample\|.template'
grep -q "^\.env$\|^\.env\.\*" .gitignore 2>/dev/null && echo ".env IS gitignored" || echo "WARNING: .env NOT in .gitignore"
```
**CI configs with inline secrets (not using secret stores):**
```bash
for f in $(find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null) .gitlab-ci.yml .circleci/config.yml; do
[ -f "$f" ] && grep -n "password:\|token:\|secret:\|api_key:" "$f" | grep -v '\${{' | grep -v 'secrets\.'
done 2>/dev/null
```
**Severity:** CRITICAL for active secret patterns in git history (AKIA, sk_live_, ghp_, xoxb-). HIGH for .env tracked by git, CI configs with inline credentials. MEDIUM for suspicious .env.example values.
**FP rules:** Placeholders ("your_", "changeme", "TODO") excluded. Test fixtures excluded unless same value in non-test code. Rotated secrets still flagged (they were exposed). `.env.local` in `.gitignore` is expected.
**Diff mode:** Replace `git log -p --all` with `git log -p <base>..HEAD`.
### Phase 3: Dependency Supply Chain
Goes beyond `npm audit`. Checks actual supply chain risk.
**Package manager detection:**
```bash
[ -f package.json ] && echo "DETECTED: npm/yarn/bun"
[ -f Gemfile ] && echo "DETECTED: bundler"
[ -f requirements.txt ] || [ -f pyproject.toml ] && echo "DETECTED: pip"
[ -f Cargo.toml ] && echo "DETECTED: cargo"
[ -f go.mod ] && echo "DETECTED: go"
```
**Standard vulnerability scan:** Run whichever package manager's audit tool is available. Each tool is optional — if not installed, note it in the report as "SKIPPED — tool not installed" with install instructions. This is informational, NOT a finding. The audit continues with whatever tools ARE available.
**Install scripts in production deps (supply chain attack vector):** For Node.js projects with hydrated `node_modules`, check production dependencies for `preinstall`, `postinstall`, or `install` scripts.
**Lockfile integrity:** Check that lockfiles exist AND are tracked by git.
**Severity:** CRITICAL for known CVEs (high/critical) in direct deps. HIGH for install scripts in prod deps / missing lockfile. MEDIUM for abandoned packages / medium CVEs / lockfile not tracked.
**FP rules:** devDependency CVEs are MEDIUM max. `node-gyp`/`cmake` install scripts expected (MEDIUM not HIGH). No-fix-available advisories without known exploits excluded. Missing lockfile for library repos (not apps) is NOT a finding.
### Phase 4: CI/CD Pipeline Security
Check who can modify workflows and what secrets they can access.
**GitHub Actions analysis:** For each workflow file, check for:
- Unpinned third-party actions (not SHA-pinned) — use Grep for `uses:` lines missing `@[sha]`
- `pull_request_target` (dangerous: fork PRs get write access)
- Script injection via `${{ github.event.* }}` in `run:` steps
- Secrets as env vars (could leak in logs)
- CODEOWNERS protection on workflow files
**Severity:** CRITICAL for `pull_request_target` + checkout of PR code / script injection via `${{ github.event.*.body }}` in `run:` steps. HIGH for unpinned third-party actions / secrets as env vars without masking. MEDIUM for missing CODEOWNERS on workflow files.
**FP rules:** First-party `actions/*` unpinned = MEDIUM not HIGH. `pull_request_target` without PR ref checkout is safe (precedent #11). Secrets in `with:` blocks (not `env:`/`run:`) are handled by runtime.
### Phase 5: Infrastructure Shadow Surface
Find shadow infrastructure with excessive access.
**Dockerfiles:** For each Dockerfile, check for missing `USER` directive (runs as root), secrets passed as `ARG`, `.env` files copied into images, exposed ports.
**Config files with prod credentials:** Use Grep to search for database connection strings (postgres://, mysql://, mongodb://, redis://) in config files, excluding localhost/127.0.0.1/example.com. Check for staging/dev configs referencing prod.
**IaC security:** For Terraform files, check for `"*"` in IAM actions/resources, hardcoded secrets in `.tf`/`.tfvars`. For K8s manifests, check for privileged containers, hostNetwork, hostPID.
**Severity:** CRITICAL for prod DB URLs with credentials in committed config / `"*"` IAM on sensitive resources / secrets baked into Docker images. HIGH for root containers in prod / staging with prod DB access / privileged K8s. MEDIUM for missing USER directive / exposed ports without documented purpose.
**FP rules:** `docker-compose.yml` for local dev with localhost = not a finding (precedent #12). Terraform `"*"` in `data` sources (read-only) excluded. K8s manifests in `test/`/`dev/`/`local/` with localhost networking excluded.
### Phase 6: Webhook & Integration Audit
Find inbound endpoints that accept anything.
**Webhook routes:** Use Grep to find files containing webhook/hook/callback route patterns. For each file, check whether it also contains signature verification (signature, hmac, verify, digest, x-hub-signature, stripe-signature, svix). Files with webhook routes but NO signature verification are findings.
**TLS verification disabled:** Use Grep to search for patterns like `verify.*false`, `VERIFY_NONE`, `InsecureSkipVerify`, `NODE_TLS_REJECT_UNAUTHORIZED.*0`.
**OAuth scope analysis:** Use Grep to find OAuth configurations and check for overly broad scopes.
**Verification approach (code-tracing only — NO live requests):** For webhook findings, trace the handler code to determine if signature verification exists anywhere in the middleware chain (parent router, middleware stack, API gateway config). Do NOT make actual HTTP requests to webhook endpoints.
**Severity:** CRITICAL for webhooks without any signature verification. HIGH for TLS verification disabled in prod code / overly broad OAuth scopes. MEDIUM for undocumented outbound data flows to third parties.
**FP rules:** TLS disabled in test code excluded. Internal service-to-service webhooks on private networks = MEDIUM max. Webhook endpoints behind API gateway that handles signature verification upstream are NOT findings — but require evidence.
### Phase 7: LLM & AI Security
Check for AI/LLM-specific vulnerabilities. This is a new attack class.
Use Grep to search for these patterns:
- **Prompt injection vectors:** User input flowing into system prompts or tool schemas — look for string interpolation near system prompt construction
- **Unsanitized LLM output:** `dangerouslySetInnerHTML`, `v-html`, `innerHTML`, `.html()`, `raw()` rendering LLM responses
- **Tool/function calling without validation:** `tool_choice`, `function_call`, `tools=`, `functions=`
- **AI API keys in code (not env vars):** `sk-` patterns, hardcoded API key assignments
- **Eval/exec of LLM output:** `eval()`, `exec()`, `Function()`, `new Function` processing AI responses
**Key checks (beyond grep):**
- Trace user content flow — does it enter system prompts or tool schemas?
- RAG poisoning: can external documents influence AI behavior via retrieval?
- Tool calling permissions: are LLM tool calls validated before execution?
- Output sanitization: is LLM output treated as trusted (rendered as HTML, executed as code)?
- Cost/resource attacks: can a user trigger unbounded LLM calls?
**Severity:** CRITICAL for user input in system prompts / unsanitized LLM output rendered as HTML / eval of LLM output. HIGH for missing tool call validation / exposed AI API keys. MEDIUM for unbounded LLM calls / RAG without input validation.
**FP rules:** User content in the user-message position of an AI conversation is NOT prompt injection (precedent #13). Only flag when user content enters system prompts, tool schemas, or function-calling contexts.
### Phase 8: Skill Supply Chain
Scan installed Claude Code skills for malicious patterns. 36% of published skills have security flaws, 13.4% are outright malicious (Snyk ToxicSkills research).
**Tier 1 — repo-local (automatic):** Scan the repo's local skills directory for suspicious patterns:
```bash
ls -la .claude/skills/ 2>/dev/null
```
Use Grep to search all local skill SKILL.md files for suspicious patterns:
- `curl`, `wget`, `fetch`, `http`, `exfiltrat` (network exfiltration)
- `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `env.`, `process.env` (credential access)
- `IGNORE PREVIOUS`, `system override`, `disregard`, `forget your instructions` (prompt injection)
**Tier 2 — global skills (requires permission):** Before scanning globally installed skills or user settings, use AskUserQuestion:
"Phase 8 can scan your globally installed AI coding agent skills and hooks for malicious patterns. This reads files outside the repo. Want to include this?"
Options: A) Yes — scan global skills too B) No — repo-local only
If approved, run the same Grep patterns on globally installed skill files and check hooks in user settings.
**Severity:** CRITICAL for credential exfiltration attempts / prompt injection in skill files. HIGH for suspicious network calls / overly broad tool permissions. MEDIUM for skills from unverified sources without review.
**FP rules:** gstack's own skills are trusted (check if skill path resolves to a known repo). Skills that use `curl` for legitimate purposes (downloading tools, health checks) need context — only flag when the target URL is suspicious or when the command includes credential variables.
### Phase 9: OWASP Top 10 Assessment
For each OWASP category, perform targeted analysis. Use the Grep tool for all searches — scope file extensions to detected stacks from Phase 0.
#### A01: Broken Access Control
- Check for missing auth on controllers/routes (skip_before_action, skip_authorization, public, no_auth)
- Check for direct object reference patterns (params[:id], req.params.id, request.args.get)
- Can user A access user B's resources by changing IDs?
- Is there horizontal/vertical privilege escalation?
#### A02: Cryptographic Failures
- Weak crypto (MD5, SHA1, DES, ECB) or hardcoded secrets
- Is sensitive data encrypted at rest and in transit?
- Are keys/secrets properly managed (env vars, not hardcoded)?
#### A03: Injection
- SQL injection: raw queries, string interpolation in SQL
- Command injection: system(), exec(), spawn(), popen
- Template injection: render with params, eval(), html_safe, raw()
- LLM prompt injection: see Phase 7 for comprehensive coverage
#### A04: Insecure Design
- Rate limits on authentication endpoints?
- Account lockout after failed attempts?
- Business logic validated server-side?
#### A05: Security Misconfiguration
- CORS configuration (wildcard origins in production?)
- CSP headers present?
- Debug mode / verbose errors in production?
#### A06: Vulnerable and Outdated Components
See **Phase 3 (Dependency Supply Chain)** for comprehensive component analysis.
#### A07: Identification and Authentication Failures
- Session management: creation, storage, invalidation
- Password policy: complexity, rotation, breach checking
- MFA: available? enforced for admin?
- Token management: JWT expiration, refresh rotation
#### A08: Software and Data Integrity Failures
See **Phase 4 (CI/CD Pipeline Security)** for pipeline protection analysis.
- Deserialization inputs validated?
- Integrity checking on external data?
#### A09: Security Logging and Monitoring Failures
- Authentication events logged?
- Authorization failures logged?
- Admin actions audit-trailed?
- Logs protected from tampering?
#### A10: Server-Side Request Forgery (SSRF)
- URL construction from user input?
- Internal service reachability from user-controlled URLs?
- Allowlist/blocklist enforcement on outbound requests?
### Phase 10: STRIDE Threat Model
For each major component identified in Phase 0, evaluate:
```
COMPONENT: [Name]
Spoofing: Can an attacker impersonate a user/service?
Tampering: Can data be modified in transit/at rest?
Repudiation: Can actions be denied? Is there an audit trail?
Information Disclosure: Can sensitive data leak?
Denial of Service: Can the component be overwhelmed?
Elevation of Privilege: Can a user gain unauthorized access?
```
### Phase 11: Data Classification
Classify all data handled by the application:
```
DATA CLASSIFICATION
═══════════════════
RESTRICTED (breach = legal liability):
- Passwords/credentials: [where stored, how protected]
- Payment data: [where stored, PCI compliance status]
- PII: [what types, where stored, retention policy]
CONFIDENTIAL (breach = business damage):
- API keys: [where stored, rotation policy]
- Business logic: [trade secrets in code?]
- User behavior data: [analytics, tracking]
INTERNAL (breach = embarrassment):
- System logs: [what they contain, who can access]
- Configuration: [what's exposed in error messages]
PUBLIC:
- Marketing content, documentation, public APIs
```
> **STOP.** Before running the scope-dependent audit phases (Phases 2-11) selected by the resolved mode, after the Phase 0 stack detection and Phase 1 attack-surface census, Read `~/.claude/skills/gstack/cso/sections/audit-phases.md` and execute it
> in full. Do not work from memory — that section is the source of truth for this step.
### Phase 12: False Positive Filtering + Active Verification
Before producing findings, run every candidate through this filter.
+6 -249
View File
@@ -67,6 +67,11 @@ When the user types `/cso`, run this skill.
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."
---
{{SECTION_INDEX:cso}}
---
## Important: Use the Grep tool for all code searches
The bash blocks throughout this skill show WHAT patterns to search for, not HOW to run them. Use Claude Code's Grep tool (which handles permissions and access correctly) rather than raw bash grep. The bash blocks are illustrative examples — do NOT copy-paste them into a terminal. Do NOT use `| head` to truncate results.
@@ -155,255 +160,7 @@ INFRASTRUCTURE SURFACE
Secret management: [env vars | KMS | vault | unknown]
```
### Phase 2: Secrets Archaeology
Scan git history for leaked credentials, check tracked `.env` files, find CI configs with inline secrets.
**Canonical pattern catalog.** The HIGH-tier credential prefixes the archaeology
greps below target (AKIA, ghp_, sk-ant-, sk_live_, xoxb-, `-----BEGIN ... PRIVATE
KEY-----`, etc.) are the same set `/spec`'s in-flight redaction blocks on. The full
3-tier taxonomy (HIGH credentials, MEDIUM PII/legal/internal, LOW) is generated from
and lives in `lib/redact-patterns.ts` — the single source of truth shared by the
`gstack-redact` engine, `/spec`, `/ship`, and the `/document-*` skills.
**Git history — known secret prefixes:**
```bash
git log -p --all -S "AKIA" --diff-filter=A -- "*.env" "*.yml" "*.yaml" "*.json" "*.toml" 2>/dev/null
git log -p --all -S "sk-" --diff-filter=A -- "*.env" "*.yml" "*.json" "*.ts" "*.js" "*.py" 2>/dev/null
git log -p --all -G "ghp_|gho_|github_pat_" 2>/dev/null
git log -p --all -G "xoxb-|xoxp-|xapp-" 2>/dev/null
git log -p --all -G "password|secret|token|api_key" -- "*.env" "*.yml" "*.json" "*.conf" 2>/dev/null
```
**.env files tracked by git:**
```bash
git ls-files '*.env' '.env.*' 2>/dev/null | grep -v '.example\|.sample\|.template'
grep -q "^\.env$\|^\.env\.\*" .gitignore 2>/dev/null && echo ".env IS gitignored" || echo "WARNING: .env NOT in .gitignore"
```
**CI configs with inline secrets (not using secret stores):**
```bash
for f in $(find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null) .gitlab-ci.yml .circleci/config.yml; do
[ -f "$f" ] && grep -n "password:\|token:\|secret:\|api_key:" "$f" | grep -v '\${{' | grep -v 'secrets\.'
done 2>/dev/null
```
**Severity:** CRITICAL for active secret patterns in git history (AKIA, sk_live_, ghp_, xoxb-). HIGH for .env tracked by git, CI configs with inline credentials. MEDIUM for suspicious .env.example values.
**FP rules:** Placeholders ("your_", "changeme", "TODO") excluded. Test fixtures excluded unless same value in non-test code. Rotated secrets still flagged (they were exposed). `.env.local` in `.gitignore` is expected.
**Diff mode:** Replace `git log -p --all` with `git log -p <base>..HEAD`.
### Phase 3: Dependency Supply Chain
Goes beyond `npm audit`. Checks actual supply chain risk.
**Package manager detection:**
```bash
[ -f package.json ] && echo "DETECTED: npm/yarn/bun"
[ -f Gemfile ] && echo "DETECTED: bundler"
[ -f requirements.txt ] || [ -f pyproject.toml ] && echo "DETECTED: pip"
[ -f Cargo.toml ] && echo "DETECTED: cargo"
[ -f go.mod ] && echo "DETECTED: go"
```
**Standard vulnerability scan:** Run whichever package manager's audit tool is available. Each tool is optional — if not installed, note it in the report as "SKIPPED — tool not installed" with install instructions. This is informational, NOT a finding. The audit continues with whatever tools ARE available.
**Install scripts in production deps (supply chain attack vector):** For Node.js projects with hydrated `node_modules`, check production dependencies for `preinstall`, `postinstall`, or `install` scripts.
**Lockfile integrity:** Check that lockfiles exist AND are tracked by git.
**Severity:** CRITICAL for known CVEs (high/critical) in direct deps. HIGH for install scripts in prod deps / missing lockfile. MEDIUM for abandoned packages / medium CVEs / lockfile not tracked.
**FP rules:** devDependency CVEs are MEDIUM max. `node-gyp`/`cmake` install scripts expected (MEDIUM not HIGH). No-fix-available advisories without known exploits excluded. Missing lockfile for library repos (not apps) is NOT a finding.
### Phase 4: CI/CD Pipeline Security
Check who can modify workflows and what secrets they can access.
**GitHub Actions analysis:** For each workflow file, check for:
- Unpinned third-party actions (not SHA-pinned) — use Grep for `uses:` lines missing `@[sha]`
- `pull_request_target` (dangerous: fork PRs get write access)
- Script injection via `${{ github.event.* }}` in `run:` steps
- Secrets as env vars (could leak in logs)
- CODEOWNERS protection on workflow files
**Severity:** CRITICAL for `pull_request_target` + checkout of PR code / script injection via `${{ github.event.*.body }}` in `run:` steps. HIGH for unpinned third-party actions / secrets as env vars without masking. MEDIUM for missing CODEOWNERS on workflow files.
**FP rules:** First-party `actions/*` unpinned = MEDIUM not HIGH. `pull_request_target` without PR ref checkout is safe (precedent #11). Secrets in `with:` blocks (not `env:`/`run:`) are handled by runtime.
### Phase 5: Infrastructure Shadow Surface
Find shadow infrastructure with excessive access.
**Dockerfiles:** For each Dockerfile, check for missing `USER` directive (runs as root), secrets passed as `ARG`, `.env` files copied into images, exposed ports.
**Config files with prod credentials:** Use Grep to search for database connection strings (postgres://, mysql://, mongodb://, redis://) in config files, excluding localhost/127.0.0.1/example.com. Check for staging/dev configs referencing prod.
**IaC security:** For Terraform files, check for `"*"` in IAM actions/resources, hardcoded secrets in `.tf`/`.tfvars`. For K8s manifests, check for privileged containers, hostNetwork, hostPID.
**Severity:** CRITICAL for prod DB URLs with credentials in committed config / `"*"` IAM on sensitive resources / secrets baked into Docker images. HIGH for root containers in prod / staging with prod DB access / privileged K8s. MEDIUM for missing USER directive / exposed ports without documented purpose.
**FP rules:** `docker-compose.yml` for local dev with localhost = not a finding (precedent #12). Terraform `"*"` in `data` sources (read-only) excluded. K8s manifests in `test/`/`dev/`/`local/` with localhost networking excluded.
### Phase 6: Webhook & Integration Audit
Find inbound endpoints that accept anything.
**Webhook routes:** Use Grep to find files containing webhook/hook/callback route patterns. For each file, check whether it also contains signature verification (signature, hmac, verify, digest, x-hub-signature, stripe-signature, svix). Files with webhook routes but NO signature verification are findings.
**TLS verification disabled:** Use Grep to search for patterns like `verify.*false`, `VERIFY_NONE`, `InsecureSkipVerify`, `NODE_TLS_REJECT_UNAUTHORIZED.*0`.
**OAuth scope analysis:** Use Grep to find OAuth configurations and check for overly broad scopes.
**Verification approach (code-tracing only — NO live requests):** For webhook findings, trace the handler code to determine if signature verification exists anywhere in the middleware chain (parent router, middleware stack, API gateway config). Do NOT make actual HTTP requests to webhook endpoints.
**Severity:** CRITICAL for webhooks without any signature verification. HIGH for TLS verification disabled in prod code / overly broad OAuth scopes. MEDIUM for undocumented outbound data flows to third parties.
**FP rules:** TLS disabled in test code excluded. Internal service-to-service webhooks on private networks = MEDIUM max. Webhook endpoints behind API gateway that handles signature verification upstream are NOT findings — but require evidence.
### Phase 7: LLM & AI Security
Check for AI/LLM-specific vulnerabilities. This is a new attack class.
Use Grep to search for these patterns:
- **Prompt injection vectors:** User input flowing into system prompts or tool schemas — look for string interpolation near system prompt construction
- **Unsanitized LLM output:** `dangerouslySetInnerHTML`, `v-html`, `innerHTML`, `.html()`, `raw()` rendering LLM responses
- **Tool/function calling without validation:** `tool_choice`, `function_call`, `tools=`, `functions=`
- **AI API keys in code (not env vars):** `sk-` patterns, hardcoded API key assignments
- **Eval/exec of LLM output:** `eval()`, `exec()`, `Function()`, `new Function` processing AI responses
**Key checks (beyond grep):**
- Trace user content flow — does it enter system prompts or tool schemas?
- RAG poisoning: can external documents influence AI behavior via retrieval?
- Tool calling permissions: are LLM tool calls validated before execution?
- Output sanitization: is LLM output treated as trusted (rendered as HTML, executed as code)?
- Cost/resource attacks: can a user trigger unbounded LLM calls?
**Severity:** CRITICAL for user input in system prompts / unsanitized LLM output rendered as HTML / eval of LLM output. HIGH for missing tool call validation / exposed AI API keys. MEDIUM for unbounded LLM calls / RAG without input validation.
**FP rules:** User content in the user-message position of an AI conversation is NOT prompt injection (precedent #13). Only flag when user content enters system prompts, tool schemas, or function-calling contexts.
### Phase 8: Skill Supply Chain
Scan installed Claude Code skills for malicious patterns. 36% of published skills have security flaws, 13.4% are outright malicious (Snyk ToxicSkills research).
**Tier 1 — repo-local (automatic):** Scan the repo's local skills directory for suspicious patterns:
```bash
ls -la .claude/skills/ 2>/dev/null
```
Use Grep to search all local skill SKILL.md files for suspicious patterns:
- `curl`, `wget`, `fetch`, `http`, `exfiltrat` (network exfiltration)
- `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `env.`, `process.env` (credential access)
- `IGNORE PREVIOUS`, `system override`, `disregard`, `forget your instructions` (prompt injection)
**Tier 2 — global skills (requires permission):** Before scanning globally installed skills or user settings, use AskUserQuestion:
"Phase 8 can scan your globally installed AI coding agent skills and hooks for malicious patterns. This reads files outside the repo. Want to include this?"
Options: A) Yes — scan global skills too B) No — repo-local only
If approved, run the same Grep patterns on globally installed skill files and check hooks in user settings.
**Severity:** CRITICAL for credential exfiltration attempts / prompt injection in skill files. HIGH for suspicious network calls / overly broad tool permissions. MEDIUM for skills from unverified sources without review.
**FP rules:** gstack's own skills are trusted (check if skill path resolves to a known repo). Skills that use `curl` for legitimate purposes (downloading tools, health checks) need context — only flag when the target URL is suspicious or when the command includes credential variables.
### Phase 9: OWASP Top 10 Assessment
For each OWASP category, perform targeted analysis. Use the Grep tool for all searches — scope file extensions to detected stacks from Phase 0.
#### A01: Broken Access Control
- Check for missing auth on controllers/routes (skip_before_action, skip_authorization, public, no_auth)
- Check for direct object reference patterns (params[:id], req.params.id, request.args.get)
- Can user A access user B's resources by changing IDs?
- Is there horizontal/vertical privilege escalation?
#### A02: Cryptographic Failures
- Weak crypto (MD5, SHA1, DES, ECB) or hardcoded secrets
- Is sensitive data encrypted at rest and in transit?
- Are keys/secrets properly managed (env vars, not hardcoded)?
#### A03: Injection
- SQL injection: raw queries, string interpolation in SQL
- Command injection: system(), exec(), spawn(), popen
- Template injection: render with params, eval(), html_safe, raw()
- LLM prompt injection: see Phase 7 for comprehensive coverage
#### A04: Insecure Design
- Rate limits on authentication endpoints?
- Account lockout after failed attempts?
- Business logic validated server-side?
#### A05: Security Misconfiguration
- CORS configuration (wildcard origins in production?)
- CSP headers present?
- Debug mode / verbose errors in production?
#### A06: Vulnerable and Outdated Components
See **Phase 3 (Dependency Supply Chain)** for comprehensive component analysis.
#### A07: Identification and Authentication Failures
- Session management: creation, storage, invalidation
- Password policy: complexity, rotation, breach checking
- MFA: available? enforced for admin?
- Token management: JWT expiration, refresh rotation
#### A08: Software and Data Integrity Failures
See **Phase 4 (CI/CD Pipeline Security)** for pipeline protection analysis.
- Deserialization inputs validated?
- Integrity checking on external data?
#### A09: Security Logging and Monitoring Failures
- Authentication events logged?
- Authorization failures logged?
- Admin actions audit-trailed?
- Logs protected from tampering?
#### A10: Server-Side Request Forgery (SSRF)
- URL construction from user input?
- Internal service reachability from user-controlled URLs?
- Allowlist/blocklist enforcement on outbound requests?
### Phase 10: STRIDE Threat Model
For each major component identified in Phase 0, evaluate:
```
COMPONENT: [Name]
Spoofing: Can an attacker impersonate a user/service?
Tampering: Can data be modified in transit/at rest?
Repudiation: Can actions be denied? Is there an audit trail?
Information Disclosure: Can sensitive data leak?
Denial of Service: Can the component be overwhelmed?
Elevation of Privilege: Can a user gain unauthorized access?
```
### Phase 11: Data Classification
Classify all data handled by the application:
```
DATA CLASSIFICATION
═══════════════════
RESTRICTED (breach = legal liability):
- Passwords/credentials: [where stored, how protected]
- Payment data: [where stored, PCI compliance status]
- PII: [what types, where stored, retention policy]
CONFIDENTIAL (breach = business damage):
- API keys: [where stored, rotation policy]
- Business logic: [trade secrets in code?]
- User behavior data: [analytics, tracking]
INTERNAL (breach = embarrassment):
- System logs: [what they contain, who can access]
- Configuration: [what's exposed in error messages]
PUBLIC:
- Marketing content, documentation, public APIs
```
{{SECTION:audit-phases}}
### Phase 12: False Positive Filtering + Active Verification
Before producing findings, run every candidate through this filter.
+251
View File
@@ -0,0 +1,251 @@
<!-- AUTO-GENERATED from audit-phases.md.tmpl — do not edit directly -->
<!-- Regenerate: bun run gen:skill-docs -->
### Phase 2: Secrets Archaeology
Scan git history for leaked credentials, check tracked `.env` files, find CI configs with inline secrets.
**Canonical pattern catalog.** The HIGH-tier credential prefixes the archaeology
greps below target (AKIA, ghp_, sk-ant-, sk_live_, xoxb-, `-----BEGIN ... PRIVATE
KEY-----`, etc.) are the same set `/spec`'s in-flight redaction blocks on. The full
3-tier taxonomy (HIGH credentials, MEDIUM PII/legal/internal, LOW) is generated from
and lives in `lib/redact-patterns.ts` — the single source of truth shared by the
`gstack-redact` engine, `/spec`, `/ship`, and the `/document-*` skills.
**Git history — known secret prefixes:**
```bash
git log -p --all -S "AKIA" --diff-filter=A -- "*.env" "*.yml" "*.yaml" "*.json" "*.toml" 2>/dev/null
git log -p --all -S "sk-" --diff-filter=A -- "*.env" "*.yml" "*.json" "*.ts" "*.js" "*.py" 2>/dev/null
git log -p --all -G "ghp_|gho_|github_pat_" 2>/dev/null
git log -p --all -G "xoxb-|xoxp-|xapp-" 2>/dev/null
git log -p --all -G "password|secret|token|api_key" -- "*.env" "*.yml" "*.json" "*.conf" 2>/dev/null
```
**.env files tracked by git:**
```bash
git ls-files '*.env' '.env.*' 2>/dev/null | grep -v '.example\|.sample\|.template'
grep -q "^\.env$\|^\.env\.\*" .gitignore 2>/dev/null && echo ".env IS gitignored" || echo "WARNING: .env NOT in .gitignore"
```
**CI configs with inline secrets (not using secret stores):**
```bash
for f in $(find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null) .gitlab-ci.yml .circleci/config.yml; do
[ -f "$f" ] && grep -n "password:\|token:\|secret:\|api_key:" "$f" | grep -v '\${{' | grep -v 'secrets\.'
done 2>/dev/null
```
**Severity:** CRITICAL for active secret patterns in git history (AKIA, sk_live_, ghp_, xoxb-). HIGH for .env tracked by git, CI configs with inline credentials. MEDIUM for suspicious .env.example values.
**FP rules:** Placeholders ("your_", "changeme", "TODO") excluded. Test fixtures excluded unless same value in non-test code. Rotated secrets still flagged (they were exposed). `.env.local` in `.gitignore` is expected.
**Diff mode:** Replace `git log -p --all` with `git log -p <base>..HEAD`.
### Phase 3: Dependency Supply Chain
Goes beyond `npm audit`. Checks actual supply chain risk.
**Package manager detection:**
```bash
[ -f package.json ] && echo "DETECTED: npm/yarn/bun"
[ -f Gemfile ] && echo "DETECTED: bundler"
[ -f requirements.txt ] || [ -f pyproject.toml ] && echo "DETECTED: pip"
[ -f Cargo.toml ] && echo "DETECTED: cargo"
[ -f go.mod ] && echo "DETECTED: go"
```
**Standard vulnerability scan:** Run whichever package manager's audit tool is available. Each tool is optional — if not installed, note it in the report as "SKIPPED — tool not installed" with install instructions. This is informational, NOT a finding. The audit continues with whatever tools ARE available.
**Install scripts in production deps (supply chain attack vector):** For Node.js projects with hydrated `node_modules`, check production dependencies for `preinstall`, `postinstall`, or `install` scripts.
**Lockfile integrity:** Check that lockfiles exist AND are tracked by git.
**Severity:** CRITICAL for known CVEs (high/critical) in direct deps. HIGH for install scripts in prod deps / missing lockfile. MEDIUM for abandoned packages / medium CVEs / lockfile not tracked.
**FP rules:** devDependency CVEs are MEDIUM max. `node-gyp`/`cmake` install scripts expected (MEDIUM not HIGH). No-fix-available advisories without known exploits excluded. Missing lockfile for library repos (not apps) is NOT a finding.
### Phase 4: CI/CD Pipeline Security
Check who can modify workflows and what secrets they can access.
**GitHub Actions analysis:** For each workflow file, check for:
- Unpinned third-party actions (not SHA-pinned) — use Grep for `uses:` lines missing `@[sha]`
- `pull_request_target` (dangerous: fork PRs get write access)
- Script injection via `${{ github.event.* }}` in `run:` steps
- Secrets as env vars (could leak in logs)
- CODEOWNERS protection on workflow files
**Severity:** CRITICAL for `pull_request_target` + checkout of PR code / script injection via `${{ github.event.*.body }}` in `run:` steps. HIGH for unpinned third-party actions / secrets as env vars without masking. MEDIUM for missing CODEOWNERS on workflow files.
**FP rules:** First-party `actions/*` unpinned = MEDIUM not HIGH. `pull_request_target` without PR ref checkout is safe (precedent #11). Secrets in `with:` blocks (not `env:`/`run:`) are handled by runtime.
### Phase 5: Infrastructure Shadow Surface
Find shadow infrastructure with excessive access.
**Dockerfiles:** For each Dockerfile, check for missing `USER` directive (runs as root), secrets passed as `ARG`, `.env` files copied into images, exposed ports.
**Config files with prod credentials:** Use Grep to search for database connection strings (postgres://, mysql://, mongodb://, redis://) in config files, excluding localhost/127.0.0.1/example.com. Check for staging/dev configs referencing prod.
**IaC security:** For Terraform files, check for `"*"` in IAM actions/resources, hardcoded secrets in `.tf`/`.tfvars`. For K8s manifests, check for privileged containers, hostNetwork, hostPID.
**Severity:** CRITICAL for prod DB URLs with credentials in committed config / `"*"` IAM on sensitive resources / secrets baked into Docker images. HIGH for root containers in prod / staging with prod DB access / privileged K8s. MEDIUM for missing USER directive / exposed ports without documented purpose.
**FP rules:** `docker-compose.yml` for local dev with localhost = not a finding (precedent #12). Terraform `"*"` in `data` sources (read-only) excluded. K8s manifests in `test/`/`dev/`/`local/` with localhost networking excluded.
### Phase 6: Webhook & Integration Audit
Find inbound endpoints that accept anything.
**Webhook routes:** Use Grep to find files containing webhook/hook/callback route patterns. For each file, check whether it also contains signature verification (signature, hmac, verify, digest, x-hub-signature, stripe-signature, svix). Files with webhook routes but NO signature verification are findings.
**TLS verification disabled:** Use Grep to search for patterns like `verify.*false`, `VERIFY_NONE`, `InsecureSkipVerify`, `NODE_TLS_REJECT_UNAUTHORIZED.*0`.
**OAuth scope analysis:** Use Grep to find OAuth configurations and check for overly broad scopes.
**Verification approach (code-tracing only — NO live requests):** For webhook findings, trace the handler code to determine if signature verification exists anywhere in the middleware chain (parent router, middleware stack, API gateway config). Do NOT make actual HTTP requests to webhook endpoints.
**Severity:** CRITICAL for webhooks without any signature verification. HIGH for TLS verification disabled in prod code / overly broad OAuth scopes. MEDIUM for undocumented outbound data flows to third parties.
**FP rules:** TLS disabled in test code excluded. Internal service-to-service webhooks on private networks = MEDIUM max. Webhook endpoints behind API gateway that handles signature verification upstream are NOT findings — but require evidence.
### Phase 7: LLM & AI Security
Check for AI/LLM-specific vulnerabilities. This is a new attack class.
Use Grep to search for these patterns:
- **Prompt injection vectors:** User input flowing into system prompts or tool schemas — look for string interpolation near system prompt construction
- **Unsanitized LLM output:** `dangerouslySetInnerHTML`, `v-html`, `innerHTML`, `.html()`, `raw()` rendering LLM responses
- **Tool/function calling without validation:** `tool_choice`, `function_call`, `tools=`, `functions=`
- **AI API keys in code (not env vars):** `sk-` patterns, hardcoded API key assignments
- **Eval/exec of LLM output:** `eval()`, `exec()`, `Function()`, `new Function` processing AI responses
**Key checks (beyond grep):**
- Trace user content flow — does it enter system prompts or tool schemas?
- RAG poisoning: can external documents influence AI behavior via retrieval?
- Tool calling permissions: are LLM tool calls validated before execution?
- Output sanitization: is LLM output treated as trusted (rendered as HTML, executed as code)?
- Cost/resource attacks: can a user trigger unbounded LLM calls?
**Severity:** CRITICAL for user input in system prompts / unsanitized LLM output rendered as HTML / eval of LLM output. HIGH for missing tool call validation / exposed AI API keys. MEDIUM for unbounded LLM calls / RAG without input validation.
**FP rules:** User content in the user-message position of an AI conversation is NOT prompt injection (precedent #13). Only flag when user content enters system prompts, tool schemas, or function-calling contexts.
### Phase 8: Skill Supply Chain
Scan installed Claude Code skills for malicious patterns. 36% of published skills have security flaws, 13.4% are outright malicious (Snyk ToxicSkills research).
**Tier 1 — repo-local (automatic):** Scan the repo's local skills directory for suspicious patterns:
```bash
ls -la .claude/skills/ 2>/dev/null
```
Use Grep to search all local skill SKILL.md files for suspicious patterns:
- `curl`, `wget`, `fetch`, `http`, `exfiltrat` (network exfiltration)
- `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `env.`, `process.env` (credential access)
- `IGNORE PREVIOUS`, `system override`, `disregard`, `forget your instructions` (prompt injection)
**Tier 2 — global skills (requires permission):** Before scanning globally installed skills or user settings, use AskUserQuestion:
"Phase 8 can scan your globally installed AI coding agent skills and hooks for malicious patterns. This reads files outside the repo. Want to include this?"
Options: A) Yes — scan global skills too B) No — repo-local only
If approved, run the same Grep patterns on globally installed skill files and check hooks in user settings.
**Severity:** CRITICAL for credential exfiltration attempts / prompt injection in skill files. HIGH for suspicious network calls / overly broad tool permissions. MEDIUM for skills from unverified sources without review.
**FP rules:** gstack's own skills are trusted (check if skill path resolves to a known repo). Skills that use `curl` for legitimate purposes (downloading tools, health checks) need context — only flag when the target URL is suspicious or when the command includes credential variables.
### Phase 9: OWASP Top 10 Assessment
For each OWASP category, perform targeted analysis. Use the Grep tool for all searches — scope file extensions to detected stacks from Phase 0.
#### A01: Broken Access Control
- Check for missing auth on controllers/routes (skip_before_action, skip_authorization, public, no_auth)
- Check for direct object reference patterns (params[:id], req.params.id, request.args.get)
- Can user A access user B's resources by changing IDs?
- Is there horizontal/vertical privilege escalation?
#### A02: Cryptographic Failures
- Weak crypto (MD5, SHA1, DES, ECB) or hardcoded secrets
- Is sensitive data encrypted at rest and in transit?
- Are keys/secrets properly managed (env vars, not hardcoded)?
#### A03: Injection
- SQL injection: raw queries, string interpolation in SQL
- Command injection: system(), exec(), spawn(), popen
- Template injection: render with params, eval(), html_safe, raw()
- LLM prompt injection: see Phase 7 for comprehensive coverage
#### A04: Insecure Design
- Rate limits on authentication endpoints?
- Account lockout after failed attempts?
- Business logic validated server-side?
#### A05: Security Misconfiguration
- CORS configuration (wildcard origins in production?)
- CSP headers present?
- Debug mode / verbose errors in production?
#### A06: Vulnerable and Outdated Components
See **Phase 3 (Dependency Supply Chain)** for comprehensive component analysis.
#### A07: Identification and Authentication Failures
- Session management: creation, storage, invalidation
- Password policy: complexity, rotation, breach checking
- MFA: available? enforced for admin?
- Token management: JWT expiration, refresh rotation
#### A08: Software and Data Integrity Failures
See **Phase 4 (CI/CD Pipeline Security)** for pipeline protection analysis.
- Deserialization inputs validated?
- Integrity checking on external data?
#### A09: Security Logging and Monitoring Failures
- Authentication events logged?
- Authorization failures logged?
- Admin actions audit-trailed?
- Logs protected from tampering?
#### A10: Server-Side Request Forgery (SSRF)
- URL construction from user input?
- Internal service reachability from user-controlled URLs?
- Allowlist/blocklist enforcement on outbound requests?
### Phase 10: STRIDE Threat Model
For each major component identified in Phase 0, evaluate:
```
COMPONENT: [Name]
Spoofing: Can an attacker impersonate a user/service?
Tampering: Can data be modified in transit/at rest?
Repudiation: Can actions be denied? Is there an audit trail?
Information Disclosure: Can sensitive data leak?
Denial of Service: Can the component be overwhelmed?
Elevation of Privilege: Can a user gain unauthorized access?
```
### Phase 11: Data Classification
Classify all data handled by the application:
```
DATA CLASSIFICATION
═══════════════════
RESTRICTED (breach = legal liability):
- Passwords/credentials: [where stored, how protected]
- Payment data: [where stored, PCI compliance status]
- PII: [what types, where stored, retention policy]
CONFIDENTIAL (breach = business damage):
- API keys: [where stored, rotation policy]
- Business logic: [trade secrets in code?]
- User behavior data: [analytics, tracking]
INTERNAL (breach = embarrassment):
- System logs: [what they contain, who can access]
- Configuration: [what's exposed in error messages]
PUBLIC:
- Marketing content, documentation, public APIs
```
+249
View File
@@ -0,0 +1,249 @@
### Phase 2: Secrets Archaeology
Scan git history for leaked credentials, check tracked `.env` files, find CI configs with inline secrets.
**Canonical pattern catalog.** The HIGH-tier credential prefixes the archaeology
greps below target (AKIA, ghp_, sk-ant-, sk_live_, xoxb-, `-----BEGIN ... PRIVATE
KEY-----`, etc.) are the same set `/spec`'s in-flight redaction blocks on. The full
3-tier taxonomy (HIGH credentials, MEDIUM PII/legal/internal, LOW) is generated from
and lives in `lib/redact-patterns.ts` — the single source of truth shared by the
`gstack-redact` engine, `/spec`, `/ship`, and the `/document-*` skills.
**Git history — known secret prefixes:**
```bash
git log -p --all -S "AKIA" --diff-filter=A -- "*.env" "*.yml" "*.yaml" "*.json" "*.toml" 2>/dev/null
git log -p --all -S "sk-" --diff-filter=A -- "*.env" "*.yml" "*.json" "*.ts" "*.js" "*.py" 2>/dev/null
git log -p --all -G "ghp_|gho_|github_pat_" 2>/dev/null
git log -p --all -G "xoxb-|xoxp-|xapp-" 2>/dev/null
git log -p --all -G "password|secret|token|api_key" -- "*.env" "*.yml" "*.json" "*.conf" 2>/dev/null
```
**.env files tracked by git:**
```bash
git ls-files '*.env' '.env.*' 2>/dev/null | grep -v '.example\|.sample\|.template'
grep -q "^\.env$\|^\.env\.\*" .gitignore 2>/dev/null && echo ".env IS gitignored" || echo "WARNING: .env NOT in .gitignore"
```
**CI configs with inline secrets (not using secret stores):**
```bash
for f in $(find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null) .gitlab-ci.yml .circleci/config.yml; do
[ -f "$f" ] && grep -n "password:\|token:\|secret:\|api_key:" "$f" | grep -v '\${{' | grep -v 'secrets\.'
done 2>/dev/null
```
**Severity:** CRITICAL for active secret patterns in git history (AKIA, sk_live_, ghp_, xoxb-). HIGH for .env tracked by git, CI configs with inline credentials. MEDIUM for suspicious .env.example values.
**FP rules:** Placeholders ("your_", "changeme", "TODO") excluded. Test fixtures excluded unless same value in non-test code. Rotated secrets still flagged (they were exposed). `.env.local` in `.gitignore` is expected.
**Diff mode:** Replace `git log -p --all` with `git log -p <base>..HEAD`.
### Phase 3: Dependency Supply Chain
Goes beyond `npm audit`. Checks actual supply chain risk.
**Package manager detection:**
```bash
[ -f package.json ] && echo "DETECTED: npm/yarn/bun"
[ -f Gemfile ] && echo "DETECTED: bundler"
[ -f requirements.txt ] || [ -f pyproject.toml ] && echo "DETECTED: pip"
[ -f Cargo.toml ] && echo "DETECTED: cargo"
[ -f go.mod ] && echo "DETECTED: go"
```
**Standard vulnerability scan:** Run whichever package manager's audit tool is available. Each tool is optional — if not installed, note it in the report as "SKIPPED — tool not installed" with install instructions. This is informational, NOT a finding. The audit continues with whatever tools ARE available.
**Install scripts in production deps (supply chain attack vector):** For Node.js projects with hydrated `node_modules`, check production dependencies for `preinstall`, `postinstall`, or `install` scripts.
**Lockfile integrity:** Check that lockfiles exist AND are tracked by git.
**Severity:** CRITICAL for known CVEs (high/critical) in direct deps. HIGH for install scripts in prod deps / missing lockfile. MEDIUM for abandoned packages / medium CVEs / lockfile not tracked.
**FP rules:** devDependency CVEs are MEDIUM max. `node-gyp`/`cmake` install scripts expected (MEDIUM not HIGH). No-fix-available advisories without known exploits excluded. Missing lockfile for library repos (not apps) is NOT a finding.
### Phase 4: CI/CD Pipeline Security
Check who can modify workflows and what secrets they can access.
**GitHub Actions analysis:** For each workflow file, check for:
- Unpinned third-party actions (not SHA-pinned) — use Grep for `uses:` lines missing `@[sha]`
- `pull_request_target` (dangerous: fork PRs get write access)
- Script injection via `${{ github.event.* }}` in `run:` steps
- Secrets as env vars (could leak in logs)
- CODEOWNERS protection on workflow files
**Severity:** CRITICAL for `pull_request_target` + checkout of PR code / script injection via `${{ github.event.*.body }}` in `run:` steps. HIGH for unpinned third-party actions / secrets as env vars without masking. MEDIUM for missing CODEOWNERS on workflow files.
**FP rules:** First-party `actions/*` unpinned = MEDIUM not HIGH. `pull_request_target` without PR ref checkout is safe (precedent #11). Secrets in `with:` blocks (not `env:`/`run:`) are handled by runtime.
### Phase 5: Infrastructure Shadow Surface
Find shadow infrastructure with excessive access.
**Dockerfiles:** For each Dockerfile, check for missing `USER` directive (runs as root), secrets passed as `ARG`, `.env` files copied into images, exposed ports.
**Config files with prod credentials:** Use Grep to search for database connection strings (postgres://, mysql://, mongodb://, redis://) in config files, excluding localhost/127.0.0.1/example.com. Check for staging/dev configs referencing prod.
**IaC security:** For Terraform files, check for `"*"` in IAM actions/resources, hardcoded secrets in `.tf`/`.tfvars`. For K8s manifests, check for privileged containers, hostNetwork, hostPID.
**Severity:** CRITICAL for prod DB URLs with credentials in committed config / `"*"` IAM on sensitive resources / secrets baked into Docker images. HIGH for root containers in prod / staging with prod DB access / privileged K8s. MEDIUM for missing USER directive / exposed ports without documented purpose.
**FP rules:** `docker-compose.yml` for local dev with localhost = not a finding (precedent #12). Terraform `"*"` in `data` sources (read-only) excluded. K8s manifests in `test/`/`dev/`/`local/` with localhost networking excluded.
### Phase 6: Webhook & Integration Audit
Find inbound endpoints that accept anything.
**Webhook routes:** Use Grep to find files containing webhook/hook/callback route patterns. For each file, check whether it also contains signature verification (signature, hmac, verify, digest, x-hub-signature, stripe-signature, svix). Files with webhook routes but NO signature verification are findings.
**TLS verification disabled:** Use Grep to search for patterns like `verify.*false`, `VERIFY_NONE`, `InsecureSkipVerify`, `NODE_TLS_REJECT_UNAUTHORIZED.*0`.
**OAuth scope analysis:** Use Grep to find OAuth configurations and check for overly broad scopes.
**Verification approach (code-tracing only — NO live requests):** For webhook findings, trace the handler code to determine if signature verification exists anywhere in the middleware chain (parent router, middleware stack, API gateway config). Do NOT make actual HTTP requests to webhook endpoints.
**Severity:** CRITICAL for webhooks without any signature verification. HIGH for TLS verification disabled in prod code / overly broad OAuth scopes. MEDIUM for undocumented outbound data flows to third parties.
**FP rules:** TLS disabled in test code excluded. Internal service-to-service webhooks on private networks = MEDIUM max. Webhook endpoints behind API gateway that handles signature verification upstream are NOT findings — but require evidence.
### Phase 7: LLM & AI Security
Check for AI/LLM-specific vulnerabilities. This is a new attack class.
Use Grep to search for these patterns:
- **Prompt injection vectors:** User input flowing into system prompts or tool schemas — look for string interpolation near system prompt construction
- **Unsanitized LLM output:** `dangerouslySetInnerHTML`, `v-html`, `innerHTML`, `.html()`, `raw()` rendering LLM responses
- **Tool/function calling without validation:** `tool_choice`, `function_call`, `tools=`, `functions=`
- **AI API keys in code (not env vars):** `sk-` patterns, hardcoded API key assignments
- **Eval/exec of LLM output:** `eval()`, `exec()`, `Function()`, `new Function` processing AI responses
**Key checks (beyond grep):**
- Trace user content flow — does it enter system prompts or tool schemas?
- RAG poisoning: can external documents influence AI behavior via retrieval?
- Tool calling permissions: are LLM tool calls validated before execution?
- Output sanitization: is LLM output treated as trusted (rendered as HTML, executed as code)?
- Cost/resource attacks: can a user trigger unbounded LLM calls?
**Severity:** CRITICAL for user input in system prompts / unsanitized LLM output rendered as HTML / eval of LLM output. HIGH for missing tool call validation / exposed AI API keys. MEDIUM for unbounded LLM calls / RAG without input validation.
**FP rules:** User content in the user-message position of an AI conversation is NOT prompt injection (precedent #13). Only flag when user content enters system prompts, tool schemas, or function-calling contexts.
### Phase 8: Skill Supply Chain
Scan installed Claude Code skills for malicious patterns. 36% of published skills have security flaws, 13.4% are outright malicious (Snyk ToxicSkills research).
**Tier 1 — repo-local (automatic):** Scan the repo's local skills directory for suspicious patterns:
```bash
ls -la .claude/skills/ 2>/dev/null
```
Use Grep to search all local skill SKILL.md files for suspicious patterns:
- `curl`, `wget`, `fetch`, `http`, `exfiltrat` (network exfiltration)
- `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `env.`, `process.env` (credential access)
- `IGNORE PREVIOUS`, `system override`, `disregard`, `forget your instructions` (prompt injection)
**Tier 2 — global skills (requires permission):** Before scanning globally installed skills or user settings, use AskUserQuestion:
"Phase 8 can scan your globally installed AI coding agent skills and hooks for malicious patterns. This reads files outside the repo. Want to include this?"
Options: A) Yes — scan global skills too B) No — repo-local only
If approved, run the same Grep patterns on globally installed skill files and check hooks in user settings.
**Severity:** CRITICAL for credential exfiltration attempts / prompt injection in skill files. HIGH for suspicious network calls / overly broad tool permissions. MEDIUM for skills from unverified sources without review.
**FP rules:** gstack's own skills are trusted (check if skill path resolves to a known repo). Skills that use `curl` for legitimate purposes (downloading tools, health checks) need context — only flag when the target URL is suspicious or when the command includes credential variables.
### Phase 9: OWASP Top 10 Assessment
For each OWASP category, perform targeted analysis. Use the Grep tool for all searches — scope file extensions to detected stacks from Phase 0.
#### A01: Broken Access Control
- Check for missing auth on controllers/routes (skip_before_action, skip_authorization, public, no_auth)
- Check for direct object reference patterns (params[:id], req.params.id, request.args.get)
- Can user A access user B's resources by changing IDs?
- Is there horizontal/vertical privilege escalation?
#### A02: Cryptographic Failures
- Weak crypto (MD5, SHA1, DES, ECB) or hardcoded secrets
- Is sensitive data encrypted at rest and in transit?
- Are keys/secrets properly managed (env vars, not hardcoded)?
#### A03: Injection
- SQL injection: raw queries, string interpolation in SQL
- Command injection: system(), exec(), spawn(), popen
- Template injection: render with params, eval(), html_safe, raw()
- LLM prompt injection: see Phase 7 for comprehensive coverage
#### A04: Insecure Design
- Rate limits on authentication endpoints?
- Account lockout after failed attempts?
- Business logic validated server-side?
#### A05: Security Misconfiguration
- CORS configuration (wildcard origins in production?)
- CSP headers present?
- Debug mode / verbose errors in production?
#### A06: Vulnerable and Outdated Components
See **Phase 3 (Dependency Supply Chain)** for comprehensive component analysis.
#### A07: Identification and Authentication Failures
- Session management: creation, storage, invalidation
- Password policy: complexity, rotation, breach checking
- MFA: available? enforced for admin?
- Token management: JWT expiration, refresh rotation
#### A08: Software and Data Integrity Failures
See **Phase 4 (CI/CD Pipeline Security)** for pipeline protection analysis.
- Deserialization inputs validated?
- Integrity checking on external data?
#### A09: Security Logging and Monitoring Failures
- Authentication events logged?
- Authorization failures logged?
- Admin actions audit-trailed?
- Logs protected from tampering?
#### A10: Server-Side Request Forgery (SSRF)
- URL construction from user input?
- Internal service reachability from user-controlled URLs?
- Allowlist/blocklist enforcement on outbound requests?
### Phase 10: STRIDE Threat Model
For each major component identified in Phase 0, evaluate:
```
COMPONENT: [Name]
Spoofing: Can an attacker impersonate a user/service?
Tampering: Can data be modified in transit/at rest?
Repudiation: Can actions be denied? Is there an audit trail?
Information Disclosure: Can sensitive data leak?
Denial of Service: Can the component be overwhelmed?
Elevation of Privilege: Can a user gain unauthorized access?
```
### Phase 11: Data Classification
Classify all data handled by the application:
```
DATA CLASSIFICATION
═══════════════════
RESTRICTED (breach = legal liability):
- Passwords/credentials: [where stored, how protected]
- Payment data: [where stored, PCI compliance status]
- PII: [what types, where stored, retention policy]
CONFIDENTIAL (breach = business damage):
- API keys: [where stored, rotation policy]
- Business logic: [trade secrets in code?]
- User behavior data: [analytics, tracking]
INTERNAL (breach = embarrassment):
- System logs: [what they contain, who can access]
- Configuration: [what's exposed in error messages]
PUBLIC:
- Marketing content, documentation, public APIs
```
+14
View File
@@ -0,0 +1,14 @@
{
"$schema": "https://gstack.dev/schemas/section-manifest.json",
"skill": "cso",
"version": 1,
"note": "PASSIVE registry (v2 plan T9 / CM2). id/file/title/trigger text ONLY. Mode dispatch (## Arguments, ## Mode Resolution), always-run phases (0,1), and FP-filtering exceptions (Phase 12) stay in the always-loaded skeleton; only the scope-dependent audit phases are on demand.",
"sections": [
{
"id": "audit-phases",
"file": "audit-phases.md",
"title": "Scope-dependent audit phases: secrets, dependencies, CI/CD, infra, webhooks, LLM/AI, skill supply chain, OWASP Top 10, STRIDE, data classification (Phases 2-11)",
"trigger": "running the scope-dependent audit phases (Phases 2-11) selected by the resolved mode, after the Phase 0 stack detection and Phase 1 attack-surface census"
}
]
}
+74 -53
View File
@@ -1,16 +1,22 @@
/**
* cso security-guidance preservation test (v1.45.0.0 T6).
* cso security-guidance preservation test.
*
* The cso skill carries load-bearing security prose: OWASP Top 10 mappings,
* STRIDE threat-model phrasing, "do not auto-fix without user approval"
* gates. Codex 2nd-pass critique #9: "cso exemption too broad ... should
* still get resolver dedup, catalog trim, sectioning if safe, and targeted
* evals around must-not-miss checks."
* cso carries load-bearing security prose: OWASP Top 10 mappings, STRIDE
* threat-model phrasing, mode dispatch, and false-positive-filtering exceptions
* that must NOT be auto-discarded.
*
* This test pins the must-not-miss checks. cso gets the same resolver gate
* (T2), jargon dedup (T3), and catalog trim (T4) as every other skill — but
* its security-guidance body content stays intact. Future compression work
* that would strip this content fails CI here.
* cso is now carved (skeleton SKILL.md + sections/audit-phases.md). The
* scope-dependent audit phases (2-11) moved to the section; the mode dispatch
* (## Arguments, ## Mode Resolution), the always-run phases (0, 1), and the
* FP-filtering exceptions (Phase 12) stay always-loaded in the skeleton.
*
* Two distinct guarantees (codex outside-voice #5 — earliest-use, not loose
* substrings):
* 1. PRESERVATION — the security phrases survive somewhere in the union
* (skeleton + sections); a carve relocates, it never drops.
* 2. ALWAYS-LOADED CONTRACT — dispatch + FP-filtering directives stay in the
* skeleton, and mode dispatch precedes any STOP-Read (a directive that
* decides which sections to read can't sit behind the STOP that reads them).
*/
import { describe, test, expect } from 'bun:test';
@@ -18,69 +24,84 @@ import * as fs from 'fs';
import * as path from 'path';
const REPO_ROOT = path.resolve(import.meta.dir, '..');
const CSO_SKILL = path.join(REPO_ROOT, 'cso', 'SKILL.md');
const CSO_DIR = path.join(REPO_ROOT, 'cso');
const CSO_SKELETON = path.join(CSO_DIR, 'SKILL.md');
const MUST_PRESERVE_PHRASES = [
// OWASP / STRIDE positioning
'OWASP',
'STRIDE',
// Mode discipline
'daily',
'comprehensive',
// Severity language
'confidence',
// Active verification requirement (codex critique: "active verification")
'verif', // covers "verify", "verification", "verified"
];
function readSkeleton(): string {
return fs.readFileSync(CSO_SKELETON, 'utf-8');
}
function readUnion(): string {
let text = readSkeleton();
const dir = path.join(CSO_DIR, 'sections');
if (fs.existsSync(dir)) {
for (const f of fs.readdirSync(dir).sort()) {
if (f.endsWith('.md') && !f.endsWith('.md.tmpl')) {
text += '\n' + fs.readFileSync(path.join(dir, f), 'utf-8');
}
}
}
return text;
}
const MUST_PRESERVE_HEADINGS = [
'## Preamble', // from PREAMBLE resolver
];
// Security content that must survive the carve (checked against the UNION).
const MUST_PRESERVE_PHRASES = ['OWASP', 'STRIDE', 'daily', 'comprehensive', 'confidence', 'verif'];
describe('cso skill preserves load-bearing security guidance', () => {
test('cso/SKILL.md exists and is non-trivial', () => {
expect(fs.existsSync(CSO_SKILL)).toBe(true);
const content = fs.readFileSync(CSO_SKILL, 'utf-8');
// cso is a content-heavy security skill; under 30 KB suggests stripping went too far.
expect(content.length).toBeGreaterThan(30_000);
test('cso skeleton exists and is non-trivial', () => {
expect(fs.existsSync(CSO_SKELETON)).toBe(true);
// Skeleton stays substantial: dispatch + always-run phases + FP filtering +
// report phases are all always-loaded. Under 30 KB means too much moved out.
expect(readSkeleton().length).toBeGreaterThan(30_000);
});
test('cso preserves required security phrases (case-insensitive)', () => {
const content = fs.readFileSync(CSO_SKILL, 'utf-8').toLowerCase();
const missing: string[] = [];
for (const phrase of MUST_PRESERVE_PHRASES) {
if (!content.includes(phrase.toLowerCase())) missing.push(phrase);
}
test('security phrases survive in the union (skeleton + sections)', () => {
const union = readUnion().toLowerCase();
const missing = MUST_PRESERVE_PHRASES.filter((p) => !union.includes(p.toLowerCase()));
if (missing.length > 0) {
throw new Error(
`cso/SKILL.md is missing required security phrases: ${missing.join(', ')}. ` +
`These are load-bearing for the skill's audit posture. If you intentionally ` +
`removed them, update this test with the new phrasing.`,
`cso union is missing required security phrases: ${missing.join(', ')}. ` +
`These are load-bearing. A carve relocates them; it must not drop them.`,
);
}
});
test('cso preserves required headings', () => {
const content = fs.readFileSync(CSO_SKILL, 'utf-8');
for (const heading of MUST_PRESERVE_HEADINGS) {
expect(content).toContain(heading);
test('ALWAYS-LOADED: mode dispatch + FP-filtering stay in the skeleton', () => {
const skeleton = readSkeleton();
// Dispatch must be always-loaded — the agent resolves scope before reading sections.
expect(skeleton).toContain('## Arguments');
expect(skeleton).toContain('## Mode Resolution');
// FP-filtering with its critical exceptions is mandatory and must not be on-demand.
expect(skeleton).toContain('Phase 12');
// The "SKILL.md files are NOT documentation" exception is a must-not-miss
// security directive (skill supply-chain findings); it stays always-loaded.
expect(skeleton).toContain('NOT documentation');
});
test('EARLIEST-USE: mode dispatch precedes any STOP-Read directive (codex #6)', () => {
const skeleton = readSkeleton();
const stop = skeleton.indexOf('> **STOP.**');
const modeRes = skeleton.indexOf('## Mode Resolution');
const args = skeleton.indexOf('## Arguments');
expect(modeRes).toBeGreaterThan(-1);
expect(args).toBeGreaterThan(-1);
if (stop >= 0) {
// A dispatch directive stranded after the STOP can't govern which sections to read.
expect(args).toBeLessThan(stop);
expect(modeRes).toBeLessThan(stop);
}
});
test('cso catalog trim landed (frontmatter description ≤ 200 chars)', () => {
const content = fs.readFileSync(CSO_SKILL, 'utf-8');
const content = readSkeleton();
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
expect(fmMatch).not.toBeNull();
const fm = fmMatch![1];
const descMatch = fm.match(/^description:\s+(.+)$/m);
expect(descMatch).not.toBeNull();
const desc = descMatch![1].trim();
expect(desc.length).toBeLessThanOrEqual(200);
expect(desc).toContain('(gstack)');
const desc = fmMatch![1].match(/^description:\s+(.+)$/m);
expect(desc).not.toBeNull();
expect(desc![1].trim().length).toBeLessThanOrEqual(200);
expect(desc![1]).toContain('(gstack)');
});
test('cso routing prose moved to "## When to invoke" body section', () => {
const content = fs.readFileSync(CSO_SKILL, 'utf-8');
expect(content).toContain('## When to invoke this skill');
expect(readSkeleton()).toContain('## When to invoke this skill');
});
});
+13
View File
@@ -88,6 +88,19 @@ export function checkOrdering(root: string, guard: CarveGuard): string[] {
}
}
// 3b. Earliest-use: dispatch directives must appear BEFORE the first STOP
// (codex #6 — a directive that governs which sections to read can't sit after
// the STOP that reads them).
const firstStopIdx = skeleton.indexOf(STOP);
for (const anchor of guard.staticInvariants.mustPrecedeStop ?? []) {
const at = skeleton.indexOf(anchor);
if (at < 0) {
failures.push(`mustPrecedeStop anchor missing from skeleton: "${anchor}"`);
} else if (firstStopIdx >= 0 && at > firstStopIdx) {
failures.push(`mustPrecedeStop anchor "${anchor}" appears AFTER the STOP (stranded)`);
}
}
// 4. Heavy body moved out of the skeleton but is preserved in the union.
for (const moved of guard.staticInvariants.mustMoveToSection) {
if (skeleton.includes(moved)) {
+40
View File
@@ -31,6 +31,14 @@ export interface CarveStaticInvariants {
* universal STOP/section-index checks E2 already runs).
*/
mustStayInSkeleton: string[];
/**
* Substrings that MUST appear in the skeleton BEFORE the first STOP-Read
* (earliest-use, codex #6). For cso: mode-dispatch directives (## Arguments,
* ## Mode Resolution) must be resolved before any section is read — a dispatch
* directive stranded after the STOP can't govern which sections to read.
* Empty/undefined = skip (most skills).
*/
mustPrecedeStop?: string[];
/**
* Substrings that MUST be in the union (skeleton + sections) but MUST NOT be in
* the skeleton — i.e. the heavy body that the carve relocated. Empty = skip.
@@ -225,6 +233,38 @@ export const CARVE_GUARDS: Record<string, CarveGuard> = {
minUnionBytes: 72_000,
mustContain: ['Typography', 'Color', 'Aesthetic Direction'],
},
cso: {
skill: 'cso',
expectedSections: ['audit-phases.md'],
requiredReads: ['audit-phases.md'],
scenario:
'Run a security audit on this repository in --owasp mode (OWASP Top 10 only). Resolve the mode, do the Phase 0 stack detection and Phase 1 attack-surface census, then run the scoped audit phases and produce the findings report. Skip any step that needs network access.',
staticInvariants: {
// Dispatch + always-run + FP-filtering phases are ALWAYS loaded (security).
mustStayInSkeleton: [
'## Arguments',
'## Mode Resolution',
'### Phase 0',
'### Phase 1',
'### Phase 12',
'### Phase 13',
'### Phase 14',
],
// Earliest-use: mode must be resolvable before any section is read (codex #6).
mustPrecedeStop: ['## Arguments', '## Mode Resolution'],
// Scope-dependent audit detail moved to the section.
mustMoveToSection: [
'### Phase 2: Secrets Archaeology',
'### Phase 9: OWASP Top 10 Assessment',
'### Phase 10: STRIDE Threat Model',
],
gateAfterStop: undefined,
},
behavioral: 'prompt',
maxSkeletonBytes: 70_000,
minUnionBytes: 72_000,
mustContain: ['OWASP', 'STRIDE', 'daily', 'comprehensive', 'verif'],
},
};
/** Sorted carved-skill names. Consumers derive their lists from this — no parallel lists. */
+1 -7
View File
@@ -205,13 +205,7 @@ export function runParityChecks(opts: {
* from the size-budget / static / behavioral guards.
*/
const MONOLITH_INVARIANTS: ParityInvariant[] = [
{
skill: 'cso',
mustContain: ['OWASP', 'STRIDE', 'daily', 'comprehensive', 'verif'],
mustHaveHeadings: ['## Preamble', '## When to invoke'],
maxSizeRatio: 1.05,
minBytes: 30_000,
},
// cso is now carved — its invariant is generated from CARVE_GUARDS below.
{
skill: 'review',
mustContain: ['confidence', 'P1', 'P2'],