The Vibe Check Skill
Vibe coding is real and good: an idea becomes a working app in a weekend. Then
the app gets users, and the things that didn't matter Friday night matter
enormously — the API key sitting in client code, the endpoint that trusts the
browser to say who's logged in, the database where every user can read every
row. This skill is the bridge from "it works" to "strangers can use it":
a structured self-audit ordered by embarrassment-per-fix, honest about what
must block launch versus what can wait for week two. It reviews the user's
own app — it's a seatbelt, not a lockpick.
What This Skill Produces
- A ranked findings list: 🔴 launch-blockers / 🟡 week-one / 🟢 eventually,
each with the concrete fix (and the code-level change where code was shared)
- The attacker's tour: "here's what I'd try first on your app" — the 10-
minute walkthrough of your own front door, as motivation and test plan
- A launch checklist for this specific stack, not a generic OWASP dump
- The data honesty check: what you're storing, whether you need it, and
whether you can delete it when a user asks
Required Inputs
Ask for (if not already provided):
- What the app does and who's about to use it (5 friends? the internet?
payments? minors? — the bar moves)
- The stack: framework, hosting, database, auth approach, AI APIs used
- Access to look: the repo/key files pasted, or answers to the checklist
questions honestly ("is the Supabase anon key doing all your auth? be
honest")
- What the AI assistant built vs what the user wrote/reviewed — unreviewed
generated code is where the holes cluster
Framework: the five embarrassing holes (check these first)
- Secrets in the client. API keys in frontend JS, .env committed to the
repo, keys in the mobile bundle. Fix: server-side proxy for anything with
a bill or a scope; rotate anything that ever shipped to a browser — it's
burned, rotation is not optional.
- Auth theater. The UI hides the admin button but the endpoint answers
anyone; user ID taken from the request body; "logged in" checked in React
but not on the server. Fix: every endpoint re-checks identity and
authorization server-side; the client is a rumor, not a witness.
- The database trusts everyone. Default-open row-level security, every
user can query every row, the AI wrote
select * where it meant
where user_id =. Fix: RLS/scoped queries, then test as a second user —
the two-account test finds most of it.
- Input goes straight in. Unvalidated input into queries, prompts
(injection into your LLM calls — your system prompt is not a secret once
users can talk to it), file uploads with no limits, HTML rendered unescaped.
Fix: validate server-side, parameterize, cap sizes, escape output, treat
LLM output shown to other users as untrusted input too.
- Data with no exit. Storing more than needed, no deletion path, AI
conversation logs kept forever by default, no answer to "delete my
account." Fix: store less, add the delete path now (retrofitting it after
growth is 10x the work), write the three-line privacy note that matches
reality.
Then the supporting cast: rate limits on anything that costs money per call
(your AI endpoints especially — one loop = one invoice) · error messages that
don't leak stack traces · dependency audit (npm audit is free) · backups
tested once · the bus factor file (how to deploy, where the keys live).
Output Format
## Vibe check: [app] — verdict: [SHIP / SHIP AFTER RED / NOT YET]
## Findings
| # | 🔴🟡🟢 | The hole | Where | The fix (specific) |
## The attacker's 10-minute tour of your app
[First thing I'd try · second · third — each mapped to a finding]
## Launch checklist (your stack)
- [ ] [concrete, checkable items]
## Data honesty
[Storing → needed? → deletable? · the 3-line privacy note]
## What's genuinely fine
[The vibe-coded parts that hold up — credit where due]
Quality Checks
Anti-Patterns
Related
[[security-threat-model]] for the grown-up version; [[injection-spotter]] for
the prompt-injection deep-dive; [[local-dev-setup]] and [[monitoring-setup-guide]]
for the operational half of "real app."
1---2name: the-vibe-check3description: Harden a vibe-coded app before strangers use it — the audit for prototypes built fast with AI: exposed secrets, missing auth checks, unvalidated input, data with no deletion path, and the five embarrassing holes every weekend build has. Use when someone says 'Claude built my app, is it safe to launch', 'harden my prototype', 'vibe check my project', or before putting real users on a hackathon build. Produces a ranked findings list with fixes, a launch-blocker line, and a 'what I'd break first' attacker's tour. Defensive review of YOUR OWN app.4---5
6# The Vibe Check Skill
7
8Vibe coding is real and good: an idea becomes a working app in a weekend. Then
9the app gets users, and the things that didn't matter Friday night matter
10enormously — the API key sitting in client code, the endpoint that trusts the
11browser to say who's logged in, the database where every user can read every
12row. This skill is the bridge from "it works" to "strangers can use it":
13a structured self-audit ordered by embarrassment-per-fix, honest about what
14must block launch versus what can wait for week two. It reviews the *user's
15own app* — it's a seatbelt, not a lockpick.
16
17## What This Skill Produces
18
19- A **ranked findings list**: 🔴 launch-blockers / 🟡 week-one / 🟢 eventually,
20 each with the concrete fix (and the code-level change where code was shared)
21- The **attacker's tour**: "here's what I'd try first on your app" — the 10-
22 minute walkthrough of your own front door, as motivation and test plan
23- A **launch checklist** for this specific stack, not a generic OWASP dump
24- The **data honesty check**: what you're storing, whether you need it, and
25 whether you can delete it when a user asks
26
27## Required Inputs
28
29Ask for (if not already provided):
30- What the app does and who's about to use it (5 friends? the internet?
31 payments? minors? — the bar moves)
32- The stack: framework, hosting, database, auth approach, AI APIs used
33- Access to look: the repo/key files pasted, or answers to the checklist
34 questions honestly ("is the Supabase anon key doing all your auth? be
35 honest")
36- What the AI assistant built vs what the user wrote/reviewed — unreviewed
37 generated code is where the holes cluster
38
39## Framework: the five embarrassing holes (check these first)
40
411. **Secrets in the client.** API keys in frontend JS, .env committed to the
42 repo, keys in the mobile bundle. Fix: server-side proxy for anything with
43 a bill or a scope; rotate anything that ever shipped to a browser — it's
44 burned, rotation is not optional.
452. **Auth theater.** The UI hides the admin button but the endpoint answers
46 anyone; user ID taken from the request body; "logged in" checked in React
47 but not on the server. Fix: every endpoint re-checks identity and
48 *authorization* server-side; the client is a rumor, not a witness.
493. **The database trusts everyone.** Default-open row-level security, every
50 user can query every row, the AI wrote `select *` where it meant
51 `where user_id =`. Fix: RLS/scoped queries, then *test as a second user* —
52 the two-account test finds most of it.
534. **Input goes straight in.** Unvalidated input into queries, prompts
54 (injection into your LLM calls — your system prompt is not a secret once
55 users can talk to it), file uploads with no limits, HTML rendered unescaped.
56 Fix: validate server-side, parameterize, cap sizes, escape output, treat
57 LLM output shown to other users as untrusted input too.
585. **Data with no exit.** Storing more than needed, no deletion path, AI
59 conversation logs kept forever by default, no answer to "delete my
60 account." Fix: store less, add the delete path now (retrofitting it after
61 growth is 10x the work), write the three-line privacy note that matches
62 reality.
63
64Then the supporting cast: rate limits on anything that costs money per call
65(your AI endpoints especially — one loop = one invoice) · error messages that
66don't leak stack traces · dependency audit (`npm audit` is free) · backups
67tested once · the bus factor file (how to deploy, where the keys live).
68
69## Output Format
70
71```
72## Vibe check: [app] — verdict: [SHIP / SHIP AFTER RED / NOT YET]
73
74## Findings
75| # | 🔴🟡🟢 | The hole | Where | The fix (specific) |
76
77## The attacker's 10-minute tour of your app
78[First thing I'd try · second · third — each mapped to a finding]
79
80## Launch checklist (your stack)
81- [ ] [concrete, checkable items]
82
83## Data honesty
84[Storing → needed? → deletable? · the 3-line privacy note]
85
86## What's genuinely fine
87[The vibe-coded parts that hold up — credit where due]
88```
89
90## Quality Checks
91
92- [ ] Findings cite the user's actual code/answers — zero generic-scanner
93 filler for holes their stack can't even have
94- [ ] Every 🔴 has a specific fix, and shipped-to-client secrets say ROTATE,
95 not just "remove"
96- [ ] The two-account test and the rate-limit-on-paid-APIs check appear
97 whenever applicable
98- [ ] The verdict line is committed — one of the three, with the 🔴 count
99 carrying the reasoning
100- [ ] Something is marked genuinely fine — an audit that only condemns
101 teaches less than one that also confirms
102
103## Anti-Patterns
104
105- [ ] Do not audit apps the user doesn't own or operate — this skill hardens
106 your own front door; decline recon on others' apps
107- [ ] Do not produce exploit code — findings name the hole and the fix; the
108 attacker's tour describes attempts, not payloads
109- [ ] Do not perfection-block a launch — the 🔴/🟡/🟢 split exists because
110 "fix everything first" means never shipping, which is its own failure
111- [ ] Do not shame the vibe coding — the weekend build was the right call;
112 this is just the Monday that follows
113
114## Related
115
116[[security-threat-model]] for the grown-up version; [[injection-spotter]] for
117the prompt-injection deep-dive; [[local-dev-setup]] and [[monitoring-setup-guide]]
118for the operational half of "real app."