|
| 1 | +# Security Safety Check |
| 2 | + |
| 3 | +When this skill is invoked, run a comprehensive security audit on the current working directory. Detect the project type automatically and run all applicable checks. |
| 4 | + |
| 5 | +## Invocation |
| 6 | + |
| 7 | +This skill activates when the user types `/safetycheck`, or says "run a safety check", "security audit", "safetycheck", or "check this project for security issues". |
| 8 | + |
| 9 | +## Execution |
| 10 | + |
| 11 | +### Step 1 — Detect Project Type |
| 12 | + |
| 13 | +Determine what kind of project this is by checking for: |
| 14 | +- `package.json` → Node.js |
| 15 | +- `requirements.txt` / `pyproject.toml` → Python |
| 16 | +- `*.sh` files at root → Shell scripts |
| 17 | +- `Cargo.toml` → Rust |
| 18 | +- `go.mod` → Go |
| 19 | +- If none match, treat as generic and run filesystem-level checks only |
| 20 | + |
| 21 | +### Step 2 — Run All 8 Security Checks |
| 22 | + |
| 23 | +Run each check against the current working directory. Use Grep, Read, Glob, and Bash tools. Report findings in a severity-rated table at the end. |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +#### Check 1: Exposed API Keys |
| 28 | + |
| 29 | +Scan source files and git history for hardcoded secrets. |
| 30 | + |
| 31 | +**Source scan** — Grep all source files for these patterns: |
| 32 | +- `AIzaSy[a-zA-Z0-9_-]{30,}` (Firebase/Google API keys) |
| 33 | +- `sk-[a-zA-Z0-9]{20,}` (OpenAI keys) |
| 34 | +- `pk_live_`, `sk_live_`, `pk_test_`, `sk_test_` (Stripe keys) |
| 35 | +- `ghp_[a-zA-Z0-9]{36}`, `gho_`, `github_pat_` (GitHub tokens) |
| 36 | +- `AKIA[0-9A-Z]{16}` (AWS access keys) |
| 37 | +- `xox[bpsa]-[a-zA-Z0-9-]+` (Slack tokens) |
| 38 | +- Hardcoded `Bearer` tokens with actual values |
| 39 | +- Any `password = "..."` or `secret = "..."` with literal values (not env vars) |
| 40 | + |
| 41 | +Exclude: test fixtures, example files, regex patterns in security scanners, `.env.example` files with placeholder values. |
| 42 | + |
| 43 | +**Git history scan** — Run: |
| 44 | +```bash |
| 45 | +git log -p --all -S "API_KEY" -S "SECRET" -S "TOKEN" -S "sk-" --max-count=30 2>/dev/null | grep -E "^\+" | grep -ivE "(process\.env|os\.environ|\.env\.example|placeholder|your_|example|test)" | head -20 |
| 46 | +``` |
| 47 | + |
| 48 | +**Tracked .env check** — Run: |
| 49 | +```bash |
| 50 | +git ls-files 2>/dev/null | grep -iE "\.env$" |
| 51 | +``` |
| 52 | + |
| 53 | +**Severity**: CRITICAL if real keys found in source or git history. HIGH if .env is tracked. PASS if clean. |
| 54 | + |
| 55 | +--- |
| 56 | + |
| 57 | +#### Check 2: Rate Limiting |
| 58 | + |
| 59 | +**Detect endpoints** — Grep for: `express`, `fastify`, `http.createServer`, `app.listen`, `app.get(`, `app.post(`, `router.` |
| 60 | + |
| 61 | +**If endpoints exist**, check for rate limiting: |
| 62 | +- Grep for: `rate-limit`, `rateLimit`, `throttle`, `@upstash/ratelimit`, `bottleneck`, `p-queue` |
| 63 | +- Check package.json dependencies for rate-limit packages |
| 64 | + |
| 65 | +**Detect outbound APIs** — Grep for: `fetch(`, `axios`, `http.request`, `got(` |
| 66 | +- If outbound calls exist, check for retry/backoff logic and 429 handling |
| 67 | + |
| 68 | +**Severity**: HIGH if public endpoints exist without rate limiting. MEDIUM if outbound APIs lack 429 handling. N/A if no endpoints. |
| 69 | + |
| 70 | +--- |
| 71 | + |
| 72 | +#### Check 3: Input Sanitization |
| 73 | + |
| 74 | +Scan for dangerous patterns: |
| 75 | +- `eval(` with non-constant arguments |
| 76 | +- `execSync(` or `exec(` with string concatenation (not `execFileSync` with array) |
| 77 | +- `innerHTML` assignments without `escapeHtml` or DOMPurify |
| 78 | +- SQL queries built with string concatenation (`"SELECT * FROM " + table`) |
| 79 | +- Template literals in URL paths with unsanitized variables: `` `/api/${userInput}` `` |
| 80 | +- `child_process.exec(` with template literals or string concat |
| 81 | +- `dangerouslySetInnerHTML` without sanitization |
| 82 | +- `source` of untrusted files in shell scripts |
| 83 | + |
| 84 | +Check for validation: |
| 85 | +- Grep for: `zod`, `joi`, `yup`, `ajv`, `validator`, `encodeURIComponent`, `escapeHtml`, `sanitize` |
| 86 | + |
| 87 | +**Severity**: CRITICAL for eval/exec with user input. HIGH for unsanitized URL paths. MEDIUM for missing validation library. PASS if clean. |
| 88 | + |
| 89 | +--- |
| 90 | + |
| 91 | +#### Check 4: RLS / Database Security |
| 92 | + |
| 93 | +**Detect database usage** — Check package.json and source for: `supabase`, `prisma`, `drizzle`, `knex`, `sequelize`, `typeorm`, `pg`, `mysql`, `sqlite`, `mongoose`, `mongodb` |
| 94 | + |
| 95 | +**If Supabase**: Check for migration files, look for `ENABLE ROW LEVEL SECURITY` in SQL files, check for policy definitions. |
| 96 | + |
| 97 | +**If any database**: Check for parameterized queries vs string concatenation. |
| 98 | + |
| 99 | +**Severity**: CRITICAL if database found without RLS/access control. HIGH if queries use string concat. N/A if no database. |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +#### Check 5: Dependency Vulnerabilities |
| 104 | + |
| 105 | +**Node.js**: Run `npm audit --json 2>/dev/null` — parse results for high/critical vulnerabilities. |
| 106 | +**Python**: Run `pip audit 2>/dev/null` if available. |
| 107 | +**Check lockfile**: Verify `package-lock.json`, `yarn.lock`, or equivalent exists. |
| 108 | +**Check outdated**: Run `npm outdated 2>/dev/null | head -10` |
| 109 | + |
| 110 | +**Severity**: CRITICAL if known high/critical vulns. MEDIUM if no lockfile. LOW if outdated packages. PASS if clean. |
| 111 | + |
| 112 | +--- |
| 113 | + |
| 114 | +#### Check 6: Gitignore Hygiene |
| 115 | + |
| 116 | +Read `.gitignore` and verify it includes: |
| 117 | +- `.env` and `.env.*` |
| 118 | +- `*.pem`, `*.key`, `*.cert` |
| 119 | +- `node_modules/` (Node.js) |
| 120 | +- `.DS_Store` |
| 121 | +- IDE folders (`.vscode/`, `.idea/`) |
| 122 | + |
| 123 | +Check for files that SHOULD be ignored but are tracked: |
| 124 | +```bash |
| 125 | +git ls-files 2>/dev/null | grep -iE "\.(env|pem|key|cert|p12|pfx|keystore)$" |
| 126 | +``` |
| 127 | + |
| 128 | +If the project is published to npm, check for `files` field in package.json or `.npmignore`. |
| 129 | + |
| 130 | +**Severity**: HIGH if .env not in .gitignore. MEDIUM if *.pem/*.key missing. LOW if minor patterns missing. PASS if complete. |
| 131 | + |
| 132 | +--- |
| 133 | + |
| 134 | +#### Check 7: CI/CD and GitHub Security |
| 135 | + |
| 136 | +Check for: |
| 137 | +- `.github/workflows/` directory — any CI at all? |
| 138 | +- `.github/dependabot.yml` — automated dependency updates? |
| 139 | +- `SECURITY.md` — vulnerability disclosure policy? |
| 140 | +- `.github/CODEOWNERS` — code ownership rules? |
| 141 | +- Branch protection (if `gh` CLI available): `gh api repos/{owner}/{repo}/branches/main/protection 2>/dev/null` |
| 142 | + |
| 143 | +**Severity**: HIGH if no CI/CD and project has dependencies. MEDIUM if missing dependabot or SECURITY.md. LOW if missing CODEOWNERS. PASS if all present. |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +#### Check 8: Error Handling |
| 148 | + |
| 149 | +Scan for patterns that leak internal details: |
| 150 | +- `res.text()` or `res.json()` results thrown directly in error messages |
| 151 | +- `catch (e) { res.send(e.message) }` or `catch (e) { return e.stack }` |
| 152 | +- `console.error` of full error objects in production code paths |
| 153 | +- Error responses that include raw API response bodies |
| 154 | + |
| 155 | +**Severity**: MEDIUM if raw error bodies are exposed to users. LOW if only logged to console. PASS if errors are sanitized. |
| 156 | + |
| 157 | +--- |
| 158 | + |
| 159 | +### Step 3 — Report Findings |
| 160 | + |
| 161 | +Output a markdown table: |
| 162 | + |
| 163 | +``` |
| 164 | +| # | Check | Status | Findings | |
| 165 | +|---|-------|--------|----------| |
| 166 | +| 1 | Exposed API Keys | PASS/CRITICAL/HIGH/MEDIUM/LOW | Details... | |
| 167 | +| 2 | Rate Limiting | ... | ... | |
| 168 | +| ... | ... | ... | ... | |
| 169 | +``` |
| 170 | + |
| 171 | +Then list specific findings with file paths and line numbers. |
| 172 | + |
| 173 | +### Step 4 — Offer Fixes |
| 174 | + |
| 175 | +For each finding that has an auto-fixable solution, offer to fix it: |
| 176 | +- Missing .gitignore patterns → offer to add them |
| 177 | +- Missing SECURITY.md → offer to create one |
| 178 | +- Missing dependabot.yml → offer to create one |
| 179 | +- execSync with string concat → offer to replace with execFileSync |
| 180 | +- Missing input validation → offer to add validation functions |
| 181 | + |
| 182 | +Ask the user before making any changes. |
0 commit comments