vibe-hardening
Vibe coded. Vibe hardened.
One-command security scanner for AI-generated code.
Language: English · 繁體中文 · 简体中文 · 한국어 · 日本語

npx vibe-hardening scan
Live at vibe-hardening.io.
Get started (5 seconds)
cd ~/projects/my-app
npx vibe-hardening scan
First time only, npx will ask Ok to proceed? — press Enter.
Requirements: Node.js 18.17+ (already installed if you've used npm, next, vite, etc.).
Common mistakes:
- Running from
~/Desktop without cd — scans your entire Desktop tree.
- Running from inside the
vibe-hardening repo itself — you'll scan the tool, not your app.
- Missing Node: install from nodejs.org if
npx is not recognised.
What it catches
Languages: JavaScript / TypeScript / Python (Django, Flask, FastAPI) / Go / Rust.
74 rules across 4 languages and 9 categories, tuned for repos generated by v0 / Lovable / Bolt / Cursor / Claude Code / Replit Agent / Windsurf / Devin.
| Secrets | OpenAI sk-proj-, Anthropic sk-ant-, Stripe sk_live_, GitHub PAT, AWS keys, Supabase service_role JWT, DB URLs, Slack tokens, SendGrid SG., Notion secret_/ntn_, Twilio Account SID + Auth Token, Google / Gemini AIzaSy..., JWT signing keys |
| Injection | SQL template-literal, NoSQL req.body, child_process.exec with interpolation, path traversal, dangerouslySetInnerHTML without sanitiser |
| Network | CORS * + credentials, CORS origin reflection, SSRF via fetch(req.body.url), open redirects |
| Auth | Missing middleware on Next.js API routes (AST), JWT alg: none, ` |
| Database | Supabase tables without RLS, policies using (true), service_role referenced from 'use client' files |
| Env misuse | NEXT_PUBLIC_*SECRET / *SERVICE_ROLE variables leaking into client bundles |
| Supply chain (net) | OSV.dev CVE lookup on package-lock.json, LLM-hallucinated package detection vs. npm registry |
| Platform fingerprint | Identifies which AI tool wrote the code to weight rules and tune output |
| Python (Django / Flask / FastAPI) | DEBUG = True, hardcoded SECRET_KEY, ALLOWED_HOSTS = ['*'], @csrf_exempt, yaml.load, pickle.loads(user_input), SQL f-string injection, subprocess(shell=True), eval(request.*), FastAPI route without Depends(get_current_user), jwt.decode(algorithms=['none']) |
Usage
npx vibe-hardening scan
npx vibe-hardening scan ./my-project
npx vibe-hardening scan --format json --output report.json
npx vibe-hardening scan --severity high
npx vibe-hardening scan --offline
npx vibe-hardening scan --changed-only
npx vibe-hardening scan --changed-only=main
npx vibe-hardening scan --verify --own
npx vibe-hardening scan --format html -o report.html
npx vibe-hardening scan --format markdown -o report.md
npx vibe-hardening scan --format json -o baseline.json
npx vibe-hardening scan --compare baseline.json
npx vibe-hardening badge -o .github/vibe-hardening.svg
npx vibe-hardening scan --roast
npx vibe-hardening scan --suggest-fix
npx vibe-hardening explain vh-secret-openai
--verify live key check
For secrets we have a verifier for (OpenAI, Anthropic, Stripe, GitHub PAT,
Slack, SendGrid, Notion, Gemini), --verify --own makes one minimal read call per
finding against the provider (list models, auth test, etc. — never
destructive) and classifies each as:
- LIVE KEY — rotate immediately (shown with estimated abuse cost, e.g.
~ est. $2,000–$5,000/mo (GPU inference resale))
- revoked — safe, housekeep at leisure
- unverified — rate-limited, offline, or no verifier for that kind
Abuse cost figures are order-of-magnitude estimates, not published
medians. Most providers do not release per-incident cost statistics.
Each entry's source field (see src/reporters/abuse-costs.ts) names
what the figure is actually derived from — community incident reports,
public abuse policies, Verizon DBIR 2024 SaaS-credential category, CISA
advisories, or explicit arithmetic from pricing × observed abuse
windows. Where no independent data exists, the source says so rather
than citing a document that doesn't exist. Treat the figure as "how
bad could this get — roughly."
--own is a deliberate seatbelt so the CLI refuses to probe keys you don't
claim to own. Without it, --verify emits a stderr warning and falls back to
detection-only.
--suggest-fix copy-paste diffs
For secret findings where the fix is obvious ("move literal → env var"),
--suggest-fix prints a unified-diff-style block you can copy directly:
▲ SUGGESTED FIXES (2)
app.ts
(1) vh-secret-openai
- const k = "sk-proj-Tc8aNm3LKuWqVJ0HbDpZ4yourkeyhere5oI7yBkQv9MaCwSdRtPlNgUeFxOiHjZkLmNbCdEf";
+ const k = process.env.OPENAI_API_KEY;
Add to .env.example:
+ OPENAI_API_KEY=
Covers 12 providers (OpenAI, Anthropic, Stripe, GitHub, Slack, SendGrid,
Notion, Twilio, Google, AWS, JWT, generic DB URL). Findings without an
obvious env-var fix (SQL injection, missing auth, etc.) are skipped — those
need contextual code changes that templated suggestions would mangle.
Never modifies your files. The output is text for you to review and
apply manually. Console-only — JSON / HTML output is unaffected. Combine
with --changed-only for the fastest pre-commit check.
--roast mode
Dry brutalist one-liners instead of neutral rule messages, plus a per-grade
quip on the score line:
CRITICAL vh-secret-openai (2:12)
OpenAI key in source. Your token bill just rang. It's scared.
snippet: sk-pro…opqr
score 42 / 100 [F] This is a hostage note to yourself.
Every shipped rule has a hand-written line (48 entries covering secrets /
injection / auth / network / Python / supply chain). Dependency CVEs get a
prefix-based roast. Unknown rule IDs fall back to the neutral message.
Console-only — the JSON and HTML reporters are completely untouched, so
CI artifacts, compliance reports, and anything machine-parseable stay
professional. Combine freely with other flags:
npx vibe-hardening scan --roast
npx vibe-hardening scan --verify --own --roast
HTML report
npx vibe-hardening scan --format html -o report.html
Single self-contained file (only Google Fonts as external dep) — safe to
email, attach in Slack, or upload as a CI artifact. Usually under 50 KB
even for 100+ findings.
Included: hero block with grade and score, severity summary counts,
grouped per-file findings with rule ID / line:column / snippet / fix,
live --verify badges (▲ LIVE KEY / ✓ REVOKED / ? UNVERIFIED), and an
inline SVG score badge you can reuse.
NOT included: raw secret values (stripped before the reporter runs),
absolute file paths (relative only), environment variables. The reporter
never reads process.env, so the HTML is safe to share.
CI integration (GitHub Actions)
Use the published action — uses: vibe-hardening/cli@v1:
name: vibe-hardening
on: [pull_request, push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: vibe-hardening/cli@v1
with:
severity: high
format: html
output: vh-report.html
changed-only: origin/${{ github.base_ref }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: vibe-hardening-report
path: vh-report.html
Inputs: cwd · severity · format · output · changed-only ·
verify · roast · version. Exits with code 1 on any critical /
high finding so CI fails fast on regressions.
Output: exit-code (use with continue-on-error: true to gate
deployments without failing the action).
Most teams skip verify: true in CI and run it locally only — live
provider calls in CI are usually the wrong time to discover a rate limit.
Badge for README
npx vibe-hardening badge -o .github/vibe-hardening.svg
Then reference it in your top-level README:

Run as a post-merge step on main to keep it current. The SVG is around
500 bytes and has no runtime — renders natively on GitHub.
Agent Scan (new in 0.4.0)
vibe-hardening now scans the AI agent skill files on your machine — not just code. Skills are markdown + scripts that agent platforms load into their context at runtime, and they're a new attack surface: hardcoded API keys in SKILL.md, prompt injection in the description, dangerous shell in scripts/, MCP server typosquats, and so on.
npx vibe-hardening agent scan
Auto-detects skill installs for Cursor, Claude Code, OpenClaw, Hermes, Gemini CLI, Goose, OpenCode, Codex, Trae, Factory (and any other tool following the ~/.<agent>/skills/ pattern).
What it catches (65 rules across 5 packs):
- Hardcoded secrets — reuses the same 27 secret-detection rules as
vh scan, retargeted to skill files / configs / .env. Hermes specifically stores all secrets in ~/.hermes/.env; that file is included.
- Prompt injection — 11 patterns: "ignore previous instructions", role overrides, ChatML control tokens, Llama
[INST] / <<SYS>> tags, zero-width hidden characters.
- Dangerous shell — 14 patterns:
rm -rf /, curl | sh, persistence into .bashrc / authorized_keys, fork bombs, etc.
- Skill schema — missing required fields,
scripts/ directories not mentioned in the body (hidden capability), sensitive path + network exfil verb in same paragraph, env-dump patterns, skill folder names typosquatting popular skills.
- MCP server config —
mcp.json issues: non-TLS endpoints, localhost residue, secrets in env blocks, server-name typosquats, npx -y of unverified packages.
npx vibe-hardening agent scan
npx vibe-hardening agent scan --target cursor
npx vibe-hardening agent scan --rule b,c
npx vibe-hardening agent scan --format json -o agent-report.json
npx vibe-hardening agent scan --no-telemetry
Built before the first skill compromise hits the news. Supply-chain attacks on agent platforms are inevitable; the only question is timing. This scanner is the early warning.
Telemetry (opt-in)
vibe-hardening runs on your machine. Your code, your secrets, your file paths — none of those leave your laptop. After the first interactive scan, the CLI asks once whether you want to share anonymous stats so we can tell which rules need work:
▲ vibe-hardening · first run — help us harden the rules
We collect: rule IDs that fired, AI platform fingerprint,
CLI version, scan duration, file count, score, anon UUID.
We never : your code, secrets, file names, paths, IP, email.
Opt in later: vibe-hardening config set telemetry on
Privacy: https://vibe-hardening.io/privacy
Share anonymous scan stats? [y/N]
Default is no — only an explicit y / yes opts in. Configurable any time:
vibe-hardening config show
vibe-hardening config set telemetry on
vibe-hardening config set telemetry off
Universal opt-outs are honoured even if your local config says on:
DO_NOT_TRACK=1, CI=1, VH_TELEMETRY_DISABLED=1, or VH_TELEMETRY=off.
Full schema, retention, and source-code receipts: https://vibe-hardening.io/privacy.
Platform detection
On start, vibe-hardening fingerprints the repo and identifies the generator:
vibe-hardening scan complete · 147 files · 412ms
platform v0 (74% confidence)
Supported: v0 / lovable / bolt / cursor / claude-code / replit-agent / windsurf / devin.
Status
Preview release — Phase 1 MVP targeting 2026-05-13 on Product Hunt.
Current coverage (v0.4.0):
- Languages: JavaScript / TypeScript / Python / Go / Rust
- 6 engines: RLS diff · JWT payload · auth AST · pattern-regex · OSV.dev · LLM hallucination
- 74 code rules · 65 agent-scan rules · 406 tests · scans typical repo in under 5 seconds
- Agent skill scanner — covers Cursor / Claude Code / OpenClaw / Hermes / Gemini CLI / Goose / OpenCode / Codex / Trae / Factory
- Live key verification for 9 providers (OpenAI / Anthropic / Stripe / GitHub PAT / Slack / SendGrid / Notion / Twilio / Gemini)
- Estimated abuse-cost figure next to every LIVE KEY
- Output: coloured console · JSON / Markdown / standalone HTML report
- 0–100 security score with A–F grade + SVG README badge
- Inline suppression:
// vibe-hardening-disable-next-line vh-rule-id
- Platform fingerprint for 9 AI tools (incl. Trae)
- Opt-in anonymous telemetry — see Telemetry section
Post-launch:
- Phase 2 begins D+14 (2026-05-27): rule depth based on telemetry hit rates
- agent / MCP rules · Hall of Hardened scorecard ·
--fix auto-apply (under evaluation)
License
MIT © 2026 vibe-hardening contributors.