checkmyvibe 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ # checkmyvibe — AGENTS.md snippet
2
+
3
+ Paste the section below into your project's `AGENTS.md` (or the global one, e.g.
4
+ `~/.codex/AGENTS.md`, `~/.gemini/GEMINI.md`). This makes any agent that reads
5
+ AGENTS.md — Codex CLI, Gemini CLI, Cursor, opencode, Antigravity, and others —
6
+ able to discover and run checkmyvibe.
7
+
8
+ ---
9
+
10
+ ## checkmyvibe (production readiness & code quality audit)
11
+
12
+ When the user asks to "check my vibe", run a production readiness check, review
13
+ code quality, do a pre-ship sanity check, check for exposed environment variables,
14
+ check launch readiness, or asks for a scoped check (`secrets`, `auth`, `db`,
15
+ `backend`, `frontend`, `payment`) — use the checkmyvibe skill:
16
+
17
+ 1. Locate its instructions file `SKILL.md` by checking, in order:
18
+ - `.claude/skills/checkmyvibe/SKILL.md`
19
+ - `~/.claude/skills/checkmyvibe/SKILL.md`
20
+ - Search the repo for a `SKILL.md` whose frontmatter contains `name: checkmyvibe`
21
+ 2. Read it fully and follow every instruction: scope selection, all applicable
22
+ checks, evidence/confidence rules, severity rubric, report format, and final summary.
23
+ 3. Run helper scripts from the `scripts/` folder next to SKILL.md where the skill
24
+ directs you to (Checks 1–4 and Check 7). They are Python 3: try `python <script> <target>`,
25
+ and if not found retry with `python3`.
26
+ 4. Save the full detailed audit report to `checkmyvibe-report.md` in the target directory,
27
+ and output the summary and verdict in the conversation response.
28
+ 5. If no scope is specified, run the full audit (all checks).
29
+
30
+ Scopes map to checks exactly as defined in SKILL.md's "Scope selection" table:
31
+ `secrets` = 1a+1b+2 · `auth` = 3 · `db` = 4 · `backend` = 1a+3+4+5+6(server)+7(server)
32
+ · `frontend` = 1b+3(client)+7(client) · `payment` = 7 · full = everything.
@@ -0,0 +1,18 @@
1
+ ---
2
+ description: checkmyvibe production readiness audit trigger and entry point
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # checkmyvibe (production readiness & code quality audit)
8
+
9
+ When the user asks to "check my vibe", run a production readiness check, review code quality, do a pre-ship sanity check, check for exposed environment variables, check launch readiness, or asks for a scoped check (`secrets`, `auth`, `db`, `backend`, `frontend`, `payment`) — use the checkmyvibe skill.
10
+
11
+ Locate its instructions file `SKILL.md` by checking, in order:
12
+ 1. `.claude/skills/checkmyvibe/SKILL.md`
13
+ 2. `~/.claude/skills/checkmyvibe/SKILL.md`
14
+ 3. Search the repo for a `SKILL.md` whose frontmatter contains `name: checkmyvibe`
15
+
16
+ Read it fully and follow every instruction: scope selection, all applicable checks, evidence/confidence rules, severity rubric, report format, and final summary. If no scope is specified, run the full audit (all checks). Scopes map to checks exactly as defined in SKILL.md's "Scope selection" table.
17
+
18
+ Run helper scripts from the `scripts/` folder next to SKILL.md where the skill directs (Checks 1–4 and Check 7). They are Python 3: try `python <script> <target>` first; if not found, retry with `python3`. Always save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory, and provide the summary and verdict in your response.
@@ -0,0 +1,19 @@
1
+ ---
2
+ description: Run a checkmyvibe production readiness audit. Optional scope argument: secrets | auth | db | backend | frontend | payment (empty = full audit).
3
+ ---
4
+
5
+ $ARGUMENTS
6
+
7
+ Run the checkmyvibe production readiness and code quality audit.
8
+
9
+ First, locate the checkmyvibe skill file `SKILL.md`. Check these paths in order:
10
+
11
+ 1. `.claude/skills/checkmyvibe/SKILL.md` (project-level install)
12
+ 2. `~/.claude/skills/checkmyvibe/SKILL.md` (global install)
13
+ 3. If neither exists, search the working directory for a file named `SKILL.md` whose frontmatter contains `name: checkmyvibe`
14
+
15
+ Read it in full and follow it completely: scope selection, checks, scripts, evidence/confidence rules, severity rubric, report format, post-fix verification, and final summary structure. Always save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory and display the summary and verdict in your response.
16
+
17
+ **Scope handling:** interpret `$ARGUMENTS` above as the scope keyword plus an optional target directory (e.g. `secrets src/`). Valid scopes: `secrets`, `auth`, `db`, `backend`, `frontend`, `payment`. No arguments means a full audit across all checks (1a, 1b, 2, 3, 4, 5, 6, 7). Run only the checks mapped to the chosen scope in SKILL.md's scope table and list skipped checks in the final summary.
18
+
19
+ Helper scripts live in the `scripts/` folder next to SKILL.md. They are Python 3: try `python <script> <target>` first; if `python` is not found, retry with `python3`.
@@ -20,27 +20,33 @@ This is an **authentication-only check** (Check 3). Checks 1a/1b, 2, 4, 5, 6, an
20
20
  python <skill_dir>/scripts/check_auth_patterns.py <target>
21
21
  ```
22
22
 
23
- It flags stub names (`mockAuth`, `fakeLogin`, `tempAuth`, `bypassAuth`, ...) and always-true auth functions. If Python is unavailable or it fails, say so and do the equivalent greps manually. The script skips test directories — do not report mock auth inside unit tests even if you see it manually.
23
+ It flags stub names (`mockAuth`, `fakeLogin`, `tempAuth`, `bypassAuth`), functions returning `true` unconditionally, mock user dictionary/object returns (`req.user = {...}`, `return { id: ... }`), middleware unconditionally calling `next()`, and insecure Supabase `getSession()` usage on server routes. The script skips test directories and documentation files.
24
24
 
25
25
  ## Step 2 — Manual reasoning pass (this is where the real findings are)
26
26
 
27
- The script is a first pass only. Read the actual auth code: login handlers, middleware, route guards, session checks, and every route that returns or modifies user-specific data.
27
+ The script is a first pass only. Read the actual auth code across login handlers, middleware, route guards, session checks, and every route that returns or modifies user-specific data.
28
28
 
29
29
  Findings to hunt for:
30
30
 
31
- - **Always-true stubs:** `function isAuthenticated() { return true; }`, `const checkAdmin = () => true` — Critical.
32
- - **Stub-named helpers still wired in:** `mockAuth`, `devAuth`, `bypassAuth` reachable in production paths — Critical. Properly guarded behind `NODE_ENV === 'development'` → Should Fix (env misconfig leaks these constantly); verify the guard actually covers every import/call site.
33
- - **Protected routes with no auth check at all:** list every route returning user-specific data, then check each one calls the session/auth middleware. A `/api/orders/:id` with no guard is Critical regardless of what the UI does.
34
- - **Client-side-only enforcement:** UI hides a button/route for logged-out users but the underlying API never verifies the session — Critical. Anyone calls the API directly. To confirm this you MUST read the corresponding server route; do not clear a finding from the frontend alone.
35
- - **Commented-out auth checks** with an active bypass nearby.
36
- - **JWT/session verification gaps:** tokens decoded but not verified (`jwt.decode` instead of `jwt.verify`, no algorithm pinning), sessions accepted from client-controlled storage without server validation — Critical.
31
+ - **Always-true stubs & mock user objects:** `function isAuthenticated() { return true; }`, `req.user = { id: "demo", role: "admin" }`, middleware calling `next()` unconditionally with a TODO comment — **Critical**.
32
+ - **Stub-named helpers still wired in:** `mockAuth`, `devAuth`, `bypassAuth` reachable in production paths — **Critical**. Properly guarded behind `NODE_ENV === 'development'` → **Should Fix** (environment misconfigurations frequently expose these); verify the guard covers every call site.
33
+ - **Provider-specific security gotchas:**
34
+ - **Clerk:** Check `middleware.ts` matcher regexes. If `/api/(.*)` is omitted from the protected matcher, or if Clerk v5 `auth.protect()` is omitted from sensitive API routes → **Critical**.
35
+ - **NextAuth / Auth.js:** Missing `AUTH_SECRET` / `NEXTAUTH_SECRET` in production configuration; exposing sensitive user properties or database credentials inside client session callbacks → **Should Fix**.
36
+ - **Supabase Auth:** Using `supabase.auth.getSession()` on the server (Server Components, API routes, Server Actions) instead of `supabase.auth.getUser()`. `getSession()` reads local cookies without re-validating the token with the Supabase Auth server → **Critical**.
37
+ - **Firebase Auth:** Unverified `auth.currentUser` on the client trusted on server routes without server-side `admin.auth().verifyIdToken()`.
38
+ - **Protected routes with no auth check at all:** Compare routes that return or modify user-specific data against route definitions. Any route touching user records with no guard is **Critical**.
39
+ - **Client-side-only enforcement:** UI hides a button or redirects on the client (`{user.isAdmin && <AdminPanel />}`), but the underlying API endpoint lacks an authentication/role check — **Critical**. Anyone can call the API directly. You MUST inspect the server route.
40
+ - **Cookie & Token Storage Security:** Auth tokens stored in browser `localStorage` (vulnerable to XSS token theft) rather than `httpOnly`, `Secure`, `SameSite=Lax/Strict` cookies → **Should Fix**.
41
+ - **Password hashing in custom auth:** Storing passwords in plaintext, or using outdated hash algorithms (MD5, SHA-1, plain SHA-256 without salt/work factor) instead of bcrypt or argon2 → **Critical**.
37
42
 
38
43
  ## Step 3 — Judgment rules
39
44
 
40
45
  - Read the function body fully before flagging or clearing — never decide from the name alone.
41
46
  - Prefer one precise finding over several weak ones; tag uncertain items `High confidence` / `Medium confidence` / `Needs manual review`.
42
- - Identify the stack's intended auth mechanism (NextAuth, Clerk, Supabase Auth, custom JWT) first; "missing" means missing relative to how routes access user data, not absence of a specific library.
47
+ - Identify the stack's intended auth mechanism (Clerk, NextAuth, Supabase Auth, Firebase, custom JWT/session) first; "missing" means missing relative to how routes access user data, not absence of a specific library.
43
48
 
44
49
  ## Report
45
50
 
51
+ Save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory following the report structure in `SKILL.md`. Output the executive summary, key findings, and verdict in your conversation response, and include a reference to `checkmyvibe-report.md`.
46
52
  Use the format, severity rubric, and final-summary structure from SKILL.md. Scope reminder: "authentication-only check — secrets, .gitignore, database rules, IDOR, input validation, and payment checks were skipped. This does not mean the app is production-ready. Run a full `/checkmyvibe` audit before launch."
@@ -14,19 +14,20 @@ Use SKILL.md **only** for the report format, severity rubric, and final-summary
14
14
 
15
15
  This is a **backend-only check**: Check 1a (server-side secrets) + Check 3 (auth) + Check 4 (db) + Check 5 (IDOR) + Check 6 server-side + Check 7 server-side. Skipped and to be listed as such in the summary: Check 1b (client-exposed secrets), Check 2 (.gitignore hygiene), and client-side views of checks 3/6/7.
16
16
 
17
- ## Step 1 — Run all three scripts
17
+ ## Step 1 — Run all four scripts
18
18
 
19
19
  ```bash
20
20
  python <skill_dir>/scripts/scan_secrets.py <target>
21
21
  python <skill_dir>/scripts/check_auth_patterns.py <target>
22
22
  python <skill_dir>/scripts/check_db_config.py <target>
23
+ python <skill_dir>/scripts/check_payment_config.py <target>
23
24
  ```
24
25
 
25
- Triage per the rules in `/checkmyvibe-secrets`, `/checkmyvibe-auth`, and `/checkmyvibe-db` respectively: live keys Critical / test keys Should Fix; mock-auth hits outside tests need manual reading; missing RLS and `USING (true)` policies are Critical on user-data tables. If Python is unavailable, do each check manually and say so in the report.
26
+ Triage findings per the rules in `/checkmyvibe-secrets`, `/checkmyvibe-auth`, `/checkmyvibe-db`, and `/checkmyvibe-payment` respectively. If Python is unavailable, do each check manually and say so in the report.
26
27
 
27
- ## Step 2 — IDOR sweep (Check 5 — spend the most time here)
28
+ ## Step 2 — IDOR / BOLA sweep (Check 5 — spend the most time here)
28
29
 
29
- This is the single most common serious flaw in AI-generated apps. Enumerate every route that takes an ID (URL param, query string, or body field) and touches a database record:
30
+ This is the single most common serious flaw in AI-generated apps. Enumerate every route, Next.js Server Action, or RPC procedure that takes an ID and touches a database record:
30
31
 
31
32
  ```js
32
33
  // Finding example — Critical: any logged-in user reads ANY order
@@ -41,22 +42,31 @@ const order = await db.query(
41
42
  if (!order) return res.status(404).json({ error: 'Not found' });
42
43
  ```
43
44
 
44
- Check GET (exposure), PUT/PATCH (unauthorized modification), and DELETE (often most damaging) for all of them. An auth guard alone is not enough — ownership must be enforced in the query or immediately after fetch.
45
+ ### Advanced IDOR Patterns to Check:
46
+ - **Multi-Tenant / Organization IDOR:** In B2B or team workspaces, verifying `organization_id = req.params.orgId` is NOT enough. You must verify that the requesting `req.user.id` is an active member/admin of `orgId` before executing the query → **Critical**.
47
+ - **Next.js Server Actions:** Functions marked `'use server'` (`export async function deleteDocument(docId)`) are public RPC endpoints. If user authentication and document ownership are not verified inside the function body, anyone can invoke the action remotely → **Critical**.
48
+ - **tRPC / GraphQL Resolvers:** Check that resolvers pulling resources by ID verify authorization in context rather than returning records purely by input ID.
49
+ - Check GET (exposure), PUT/PATCH (modification), and DELETE (often most damaging) across all endpoints.
45
50
 
46
- ## Step 3 — Server-side input handling (Check 6)
51
+ ## Step 3 — Server-side input handling & validation (Check 6)
47
52
 
48
- - SQL built by string concatenation instead of parameterized queries/ORM → Critical.
49
- - **Mass assignment:** `req.body` spread straight into ORM create/update (`prisma.user.update({ data: req.body })`, `User.findByIdAndUpdate(id, req.body)`) letting users set `role`, `plan`, `isAdmin`, `emailVerified` → Critical; non-privileged fields → Should Fix.
50
- - Unescaped user input into HTML in non-auto-escaping frameworks → flag worst cases.
51
- - Login/signup/password-reset/OTP endpoints with no rate limiting → Should Fix for payment-handling apps, Worth Reviewing otherwise.
52
- - File uploads with no type/size restriction.
53
+ - **SQL built by string concatenation** instead of parameterized queries or ORM methods → **Critical**.
54
+ - **NoSQL / MongoDB Injection:** Passing `req.body` or `req.query` directly into `find()`, `findOne()`, or `deleteMany()` without sanitization → **Critical** (`{ "$gt": "" }` bypasses checks).
55
+ - **Server-Side Request Forgery (SSRF):** Endpoints that fetch user-supplied URLs (link scrapers, webhooks, image proxies via `axios.get(req.body.url)` or `fetch()`). If URLs are not validated against private IP ranges (`127.0.0.1`, `localhost`, `169.254.169.254` AWS metadata, internal RFC1918 subnets), attackers can exfiltrate cloud credentials or hit internal services → **Critical**.
56
+ - **Mass assignment:** `req.body` spread straight into ORM create/update (`prisma.user.update({ data: req.body })`, `User.findByIdAndUpdate(id, req.body)`) letting users set `role`, `plan`, `isAdmin`, `emailVerified` → **Critical**; non-privileged fields → **Should Fix**.
57
+ - **CORS Misconfiguration:** Wildcard CORS reflection with credentials (`cors({ origin: '*', credentials: true })`) → **Critical**.
58
+ - **Rate limiting on auth endpoints:** Login, signup, password reset, and OTP endpoints with no attempt throttle allow credential stuffing and SMS toll fraud → **Should Fix**.
59
+ - **Unrestricted File Uploads:** Upload endpoints with no validation of MIME type or file size.
53
60
 
54
61
  ## Step 4 — Payment processing & webhooks (Check 7, server side)
55
62
 
56
- - Price/discount/total taken from request body, query param, or hidden field instead of looked up from the DB → Critical.
57
- - **Webhook signature verification:** every payment webhook route (Stripe, PayPal, Razorpay, Firebase) must verify the signature before trusting the body — e.g. Stripe's `stripe.webhooks.constructEvent(rawBody, sigHeader, webhookSecret)` with the raw body. A webhook route with no signature verification anywhere in its flow → Critical: anyone can POST "payment succeeded" and get their order marked paid.
58
- - Webhook handlers acting on unverified amounts read from the event body → same severity.
63
+ - Price/discount/total taken from request body, query param, or hidden field instead of looked up from the DB → **Critical**.
64
+ - **Webhook signature verification:** Every payment webhook route (**Stripe**, **Lemon Squeezy**, **Dodo Payments**, **Polar**, **Paddle**, **Razorpay**, **PayPal**) must verify cryptographic signatures before trusting the body. An unverified webhook route → **Critical** (anyone can POST fake successful payments).
65
+ - **Webhook Idempotency:** Missing event deduplication on gateway `event.id` causing duplicate credits on retried webhooks → **Should Fix**.
66
+ - **Subscription Revocation:** Missing handling for subscription cancellation/expiration events (`customer.subscription.deleted`, `subscription_cancelled`) → **Critical**.
67
+ - **Customer Portal IDOR:** Creating customer billing sessions using `req.body.customerId` instead of the session user's record → **Critical**.
59
68
 
60
69
  ## Report
61
70
 
71
+ Save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory following the report structure in `SKILL.md`. Output the executive summary, key findings, and verdict in your conversation response, and include a reference to `checkmyvibe-report.md`.
62
72
  Use the format, severity rubric, evidence/confidence rules, and post-fix verification step from SKILL.md. Fix priority when multiple issues exist: critical user exposure > auth bypass > IDOR > payment logic > config > hygiene. Scope reminder: "backend-only check — client-exposed secrets, .gitignore hygiene, and frontend-side views were skipped. This does not mean the app is production-ready. Run a full `/checkmyvibe` audit before launch."
@@ -20,32 +20,50 @@ This is a **database-only check** (Check 4). Checks 1a/1b, 2, 3, 5, 6, and 7 are
20
20
  python <skill_dir>/scripts/check_db_config.py <target>
21
21
  ```
22
22
 
23
- It scans SQL files for tables created without RLS and permissive policies (`USING (true)` / `WITH CHECK (true)`), Firestore/storage rules for `allow ...: if true`, and Realtime Database rules set to `"true"`. If Python is unavailable or it fails, do the equivalent checks by reading schema/rules files manually and say so in the report.
23
+ It scans for:
24
+ - SQL migrations/schemas for tables created without RLS and permissive policies (`USING (true)` / `WITH CHECK (true)`) in BaaS stacks.
25
+ - Firestore/storage rules for `allow ...: if true` and Realtime Database rules set to `"true"`.
26
+ - Exposed SQLite database files (`.sqlite`, `.db`) located in web-accessible directories (`public/`, `static/`, `www/`, `dist/`).
27
+ - NoSQL/MongoDB direct object injection (`find(req.body)`).
28
+ - Insecure database connection configs (`sslmode=disable`, `rejectUnauthorized: false`).
24
29
 
25
- ## Step 2 — Supabase (if used)
30
+ If Python is unavailable or it fails, do the equivalent checks by reading schema/rules files manually and say so in the report.
26
31
 
27
- - Every table holding user-specific data must have `ENABLE ROW LEVEL SECURITY`. A table without it → Critical.
28
- - Policies granting broad access fail: `FOR SELECT USING (true)`, policies `TO public/anon` with unconditional USING/CHECK → Critical.
29
- - Recommended fix pattern:
32
+ ## Step 2 — Determine the Database Architecture
33
+
34
+ Distinguish between two very different database models:
35
+
36
+ ### Branch A: Client-Exposed BaaS (Supabase, Firebase, Convex)
37
+ In these stacks, the browser connects directly to the database using an anonymous public API key. Security MUST be enforced at the database row/collection level:
38
+
39
+ - **Supabase:** Every table holding user-specific data must have `ENABLE ROW LEVEL SECURITY`. A table without it → **Critical**.
40
+ - Policies granting broad access fail: `FOR SELECT USING (true)`, policies `TO public/anon` with unconditional USING/CHECK → **Critical**.
41
+ - Fix pattern:
30
42
  ```sql
31
43
  CREATE POLICY "users see own orders" ON orders
32
44
  FOR SELECT USING (auth.uid() = user_id);
33
45
  ```
34
- - Check migrations/schema files under `supabase/migrations/`, `db/`, or wherever `.sql` files live. Also confirm RLS wasn't enabled *after* data was already readable via the anon key in earlier deployments.
46
+ - **Firebase:** `firestore.rules` containing `allow read, write: if true;` on user data collections → **Critical**. `database.rules.json` with `".read": "true"` → **Critical**.
47
+ - **Convex:** Ensure functions returning private data are defined as `internalQuery` or validate `ctx.auth.getUserIdentity()`.
35
48
 
36
- ## Step 3 — Firebase (if used)
49
+ ### Branch B: Server-Backed Databases & ORMs (Neon, AWS RDS, Prisma, Drizzle, Local DBs, Mongo)
50
+ In these stacks, client browsers never talk to the database directly; all queries flow through a backend server (Express, FastAPI, Next.js server):
37
51
 
38
- - `firestore.rules`: any `allow read, write: if true;` on collections holding user data → Critical. Test-mode rules (`allow read, write: if <timestamp>`) pasted into prod-like configs → Should Fix minimum.
39
- - `database.rules.json` (Realtime DB): `".read": "true"` / `".write": "true"` on user-data nodes → Critical.
40
- - Rules files present but clearly unused/default → Worth Reviewing; verify which project they deploy to.
52
+ - **Do NOT flag missing RLS on server-only tables:** Standard SQL migrations generated by Prisma or Drizzle do not require Postgres RLS if queries are filtered in backend application code.
53
+ - **Neon & Serverless Pooling:** Verify that serverless functions connect via connection pooling (e.g. `@neondatabase/serverless` or PgBouncer pooled connection strings). Direct unpooled Postgres connections in serverless routes cause connection exhaustion and crashes → **Should Fix**.
54
+ - **SSL / Transport Security:** Database connection URIs or pool configs with `sslmode=disable` or `rejectUnauthorized: false` transmit credentials and data in cleartext → **Critical** in production.
55
+ - **SQLite / Embedded DBs:** SQLite databases (`*.db`, `*.sqlite`, `*.sqlite3`) placed in web-accessible public folders (`public/`, `static/`) or committed to git allow arbitrary database download by any visitor → **Critical**.
56
+ - **MongoDB / NoSQL Injection:** Passing unescaped `req.body` or `req.query` directly into Mongoose/MongoDB query filters (e.g., `User.findOne(req.body)`) allows query selector injection (`{ "$gt": "" }` bypassing passwords) → **Critical**.
57
+ - **Hardcoded DB Credentials:** Database connection strings with embedded plaintext passwords committed in code or schemas (e.g., in `schema.prisma` datasource) → **Critical**.
41
58
 
42
- ## Step 4 — Storage buckets
59
+ ## Step 3 — Storage buckets
43
60
 
44
- Supabase Storage, Firebase Storage, S3:
61
+ Supabase Storage, Firebase Storage, AWS S3:
45
62
 
46
- - Public buckets holding private user content (documents, receipts, profile files) → Critical.
47
- - Public buckets for genuinely public assets (avatars, static images) → not findings; note the distinction.
63
+ - Public buckets holding private user content (documents, receipts, profile identity files) → **Critical**.
64
+ - Public buckets for genuinely public assets (avatars, static product images) → not findings; note the distinction.
48
65
 
49
66
  ## Report
50
67
 
68
+ Save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory following the report structure in `SKILL.md`. Output the executive summary, key findings, and verdict in your conversation response, and include a reference to `checkmyvibe-report.md`.
51
69
  Use the format, severity rubric, and final-summary structure from SKILL.md. Scope reminder: "database-only check — secrets, .gitignore, authentication, IDOR, input validation, and payment checks were skipped. This does not mean the app is production-ready. Run a full `/checkmyvibe` audit before launch."
@@ -12,7 +12,7 @@ Use SKILL.md **only** for the report format, severity rubric, and final-summary
12
12
 
13
13
  ## Scope
14
14
 
15
- This is a **frontend-only check**: Check 1b (client-exposed secrets) + Check 3 viewed from the client (UI-only enforcement) + Check 7 viewed from the client (client-controlled pricing). Skipped and to be listed as such in the summary: Check 1a standalone triage, Check 2 (.gitignore), Check 4 (db rules), Check 5 (IDOR sweep), and full server-side reviews of auth/input/payment.
15
+ This is a **frontend-only check**: Check 1b (client-exposed secrets) + Check 3 viewed from the client (UI-only enforcement) + Check 6 viewed from the client (DOM XSS / AI markdown rendering) + Check 7 viewed from the client (client-controlled pricing). Skipped and to be listed as such in the summary: Check 1a standalone triage, Check 2 (.gitignore), Check 4 (db rules), Check 5 (IDOR sweep), and full server-side reviews.
16
16
 
17
17
  ## Step 1 — Client-exposed secrets (run script, then manual pass)
18
18
 
@@ -22,27 +22,41 @@ python <skill_dir>/scripts/scan_secrets.py <target>
22
22
 
23
23
  Then manually inspect everything reachable from the browser:
24
24
 
25
- - Framework env prefixes bundle values INTO shipped JS: `NEXT_PUBLIC_*`, `VITE_*`, `REACT_APP_*`, `EXPO_PUBLIC_*`. Any secret behind one of these → Critical.
26
- - Supabase `service_role` key, Firebase admin SDK JSON, OpenAI/Stripe secret keys anywhere under `src/`, `app/`, `components/`, `pages/`, `public/`, or client entry files → Critical.
27
- - Publishable keys (`pk_`, Supabase anon key, Firebase web config `apiKey`) are public-by-design → NOT findings; say so explicitly so the report isn't confusing.
25
+ - **Framework Env Prefixes:** `NEXT_PUBLIC_*`, `VITE_*`, `REACT_APP_*`, `EXPO_PUBLIC_*`. Any secret behind one of these is inlined into shipped JavaScript → **Critical**.
26
+ - **React Server Component (RSC) Prop Leaks:** In Next.js App Router, check if a Server Component imports a private secret and passes it as a prop to a client component (`<ClientComponent apiKey={process.env.PRIVATE_KEY} />`). Next.js serializes all props into the client HTML payload → **Critical**.
27
+ - Supabase `service_role` key, Firebase admin SDK JSON, OpenAI (`sk-proj-`), Anthropic, or Stripe secret keys anywhere under `src/`, `app/`, `components/`, `pages/`, `public/`, or client entry files → **Critical**.
28
+ - Publishable keys (`pk_`, Supabase anon key, Firebase web config `apiKey`) are public-by-design → **NOT findings**; note this explicitly so the user isn't confused.
28
29
  - Placeholders and test-fixture values → not findings.
29
30
 
30
- ## Step 2 — UI-only auth enforcement (Check 3, client view)
31
+ ## Step 2 — DOM XSS & Unescaped AI Markdown Rendering
32
+
33
+ AI-generated applications frequently display LLM responses, user bios, or chat logs:
34
+
35
+ - Inspect components rendering HTML or markdown (`react-markdown`, `marked`, `markdown-it`).
36
+ - **Unescaped rendering:** Rendering LLM or user markdown with `dangerouslySetInnerHTML`, `v-html`, or `react-markdown` without `rehype-sanitize` or DOMPurify → **Critical** (an attacker or malicious prompt injection can inject `<script>` tags, `<img onerror=...>`, or iframe exploits directly into users' browsers).
37
+
38
+ ## Step 3 — UI-only auth enforcement (Check 3, client view)
31
39
 
32
40
  Find every place the UI gates access: redirects on protected pages, hidden nav items, disabled buttons, client route guards:
33
41
 
34
- - For each gated feature, open the corresponding API route/mutation and confirm it independently verifies the session server-side. If it does not → Critical ("hiding the button does nothing; anyone calls the API directly").
35
- - Auth state trusted purely from client storage (localStorage JWT, global store) to protect data → Critical if no server verification exists.
42
+ - For each gated feature, open the corresponding API route/mutation/Server Action and confirm it independently verifies the session server-side. If it does not → **Critical** ("hiding the button does nothing; anyone can call the endpoint directly").
43
+ - Auth state trusted purely from client storage (localStorage JWT, global store) to protect data → **Critical** if no server verification exists.
36
44
  - You must read the server routes to clear or confirm findings — a clean-looking frontend proves nothing on its own.
37
45
 
38
- ## Step 3 — Client-controlled pricing (Check 7, client view)
46
+ ## Step 4 — Client-controlled pricing (Check 7, client view)
39
47
 
40
48
  Inspect checkout/cart/pricing flows:
41
49
 
42
- - Prices, discounts, totals, or quantities computed client-side and sent as the chargeable value (hidden form fields, request bodies, query params) → Critical on the corresponding server endpoint.
50
+ - Prices, discounts, totals, or quantities computed client-side and sent as the chargeable value (hidden form fields, request bodies, query params) → **Critical** on the corresponding server endpoint.
43
51
  - Coupon codes validated only in the UI → flag the endpoint that accepts them without server-side validation.
44
52
  - Note exactly which server endpoint accepts the tainted value so the backend fix is obvious.
45
53
 
54
+ ## Step 5 — Security Headers & Analytics Data Hygiene
55
+
56
+ - **Clickjacking:** Missing `X-Frame-Options: DENY` or `Content-Security-Policy: frame-ancestors 'none'` allows malicious sites to embed the app in an invisible iframe → **Should Fix**.
57
+ - **Analytics PII auto-capture:** Session recording tools (PostHog, Hotjar, LogRocket) capturing private form fields (passwords, credit card numbers, auth tokens) without masking classes (`data-mask` / `ph-no-capture`) → **Should Fix**.
58
+
46
59
  ## Report
47
60
 
61
+ Save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory following the report structure in `SKILL.md`. Output the executive summary, key findings, and verdict in your conversation response, and include a reference to `checkmyvibe-report.md`.
48
62
  Use the format, severity rubric, and final-summary structure from SKILL.md. Scope reminder: "frontend-only check — server-side secret triage, .gitignore hygiene, database rules, IDOR, server input validation, and webhook verification were skipped. This does not mean the app is production-ready. Run a full `/checkmyvibe` audit before launch."
@@ -14,17 +14,36 @@ Use SKILL.md **only** for the report format, severity rubric, and final-summary
14
14
 
15
15
  This is a **payment/pricing-only check** (Check 7, both client and server views). Checks 1a/1b, 2, 3, 4, 5, and 6 are skipped and must be listed as skipped in the final summary. Note: if this app handles real payments, state in the report that a professional external review is strongly recommended regardless of findings.
16
16
 
17
- ## Step 1 — Map the payment surface
17
+ ## Step 1 — Run the first-pass script
18
18
 
19
- Identify the provider (Stripe, PayPal, Razorpay, Firebase-based, custom) and locate: checkout endpoints, webhook routes, cart/price calculation code (client and server), subscription/plan management, and coupon/discount handling. If there is no payment code at all, report "No issues found — no payment flow exists" and stop.
19
+ ```bash
20
+ python <skill_dir>/scripts/check_payment_config.py <target>
21
+ ```
20
22
 
21
- ## Step 2 — Server-side price trust
23
+ It scans source files for client-controlled amounts/prices in checkout endpoints, detects payment webhook routes, checks for provider signature verification (Stripe, Lemon Squeezy, Dodo Payments, Paddle, Razorpay), checks for missing subscription cancellation listeners, and detects billing portal IDOR risks.
24
+
25
+ If Python is unavailable or it fails, do the equivalent checks by reading payment handlers manually and say so in the report.
26
+
27
+ ## Step 2 — Map the payment surface
28
+
29
+ Identify all payment and merchant-of-record providers in use:
30
+ - **Stripe** (`stripe`, `@stripe/stripe-js`)
31
+ - **Dodo Payments** (AI app monetization)
32
+ - **Lemon Squeezy** (`@lemonsqueezy/lemonsqueezy.js`)
33
+ - **Polar.sh** (`@polar-sh/sdk`)
34
+ - **Paddle** (`@paddle/paddle-node-sdk`)
35
+ - **Razorpay** (`razorpay`)
36
+ - **PayPal** (`@paypal/checkout-server-sdk`)
37
+
38
+ Locate checkout endpoints, webhook routes, cart/price calculation code, subscription tier handlers, and coupon/discount handling. If there is no payment code at all, report "No issues found — no payment flow exists" and stop.
39
+
40
+ ## Step 3 — Server-side price trust
22
41
 
23
42
  For each chargeable action:
24
43
 
25
- - Is the amount read from the request (body field, query param, hidden form field) or computed from client-supplied data? → Critical:
44
+ - Is the amount read from the request (body field, query param, hidden form field) or computed from client-supplied data? → **Critical**:
26
45
  ```js
27
- // Finding example — Critical
46
+ // Finding example — Critical: client controls price
28
47
  const { productId, price } = req.body;
29
48
  await chargeCard(req.user.paymentMethod, price);
30
49
 
@@ -33,20 +52,40 @@ For each chargeable action:
33
52
  const product = await db.query('SELECT price FROM products WHERE id = $1', [productId]);
34
53
  await chargeCard(req.user.paymentMethod, product.price);
35
54
  ```
36
- - Quantities, currency, plan tiers, or seat counts accepted from the client and multiplied into totals without server-side lookup → same severity.
37
- - Coupons/discounts validated only on the client, or discount values sent by the client rather than looked up server-side → Critical.
38
- - Free-trial/trial-flag booleans trusted from request bodies → Critical (anyone posts `trial: true` forever).
55
+ - Quantities, currency, plan tiers, or seat counts accepted from the client and multiplied into totals without server-side validation → same severity.
56
+ - Coupons/discounts validated only on the client, or discount values sent by the client rather than looked up server-side → **Critical**.
57
+ - Free-trial/trial-flag booleans trusted from request bodies (`req.body.trial = true`) → **Critical** (anyone posts `trial: true` forever).
39
58
 
40
- ## Step 3 — Webhook signature verification (most-missed check)
59
+ ## Step 4 — Webhook signature verification across providers
41
60
 
42
61
  Every payment webhook route must verify authenticity BEFORE trusting or acting on its body:
43
62
 
44
- - Stripe: `stripe.webhooks.constructEvent(rawBody, sigHeader, process.env.STRIPE_WEBHOOK_SECRET)` with `express.raw({ type: 'application/json' })` on the route. No signature verification anywhere in the handler chain → Critical: anyone who finds the URL can POST a fake `payment_intent.succeeded` and get orders marked paid for free.
45
- - PayPal: `verify-webhook-signature` API call missing → Critical.
46
- - Razorpay: missing `verifyPaymentSignature` / HMAC comparison → Critical.
47
- - Firebase/custom webhooks: no shared-secret header compared server-side → Critical.
48
- - Also flag webhook handlers that fulfill orders based on amounts read from the unverified event payload instead of re-fetching them server-side.
63
+ - **Stripe:** `stripe.webhooks.constructEvent(rawBody, sigHeader, process.env.STRIPE_WEBHOOK_SECRET)` with `express.raw({ type: 'application/json' })`.
64
+ - **Lemon Squeezy:** Verify `x-signature` header using `crypto.createHmac('sha256', secret).update(rawBody).digest('hex')` (with timing-safe comparison).
65
+ - **Dodo Payments:** Verify webhook signature header via Dodo SDK or HMAC verification.
66
+ - **Paddle:** Verify signature with `paddle.webhooks.unmarshal` or HMAC check.
67
+ - **Razorpay:** `validateWebhookSignature` or `crypto.createHmac('sha256', secret)` comparison.
68
+ - **PayPal:** `verify-webhook-signature` API call.
69
+
70
+ No signature verification anywhere in the handler chain → **Critical**: anyone who finds the URL can POST a fake "payment succeeded" event and get orders or licenses marked paid for free.
71
+
72
+ ## Step 5 — Webhook Idempotency & Replay Attack Prevention
73
+
74
+ Payment gateways retry webhooks if an endpoint takes >3s or returns 5xx:
75
+ - Check if webhook handlers record the processed gateway event ID (`event.id`) in the database before granting access or fulfilling orders.
76
+ - If missing, a retried webhook can cause duplicate credits, duplicate license generation, or double-shipping → **Should Fix**.
77
+
78
+ ## Step 6 — Subscription Cancellation & Revocation Lifecycle
79
+
80
+ - AI apps often handle `checkout.session.completed` to grant access, but completely omit `customer.subscription.deleted`, `customer.subscription.updated`, `subscription_cancelled`, or `invoice.payment_failed`.
81
+ - If the revocation event is not handled, users who cancel their plan or whose credit cards expire retain paid access indefinitely → **Critical**.
82
+
83
+ ## Step 7 — Billing Portal IDOR
84
+
85
+ - Inspect customer billing portal session creation (e.g. `stripe.billingPortal.sessions.create`):
86
+ - If `customerId` is taken from `req.body` rather than resolved from the authenticated user's session record in the database, users can manage, view invoices for, or cancel other customers' subscriptions → **Critical**.
49
87
 
50
88
  ## Report
51
89
 
90
+ Save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory following the report structure in `SKILL.md`. Output the executive summary, key findings, and verdict in your conversation response, and include a reference to `checkmyvibe-report.md`.
52
91
  Use the format, severity rubric, and final-summary structure from SKILL.md. Scope reminder: "payment-only check — secrets, .gitignore, authentication, database rules, IDOR, and input validation were skipped. This does not mean the app is production-ready. Run a full `/checkmyvibe` audit before launch, and get a professional security review before handling real money."
@@ -21,35 +21,44 @@ python <skill_dir>/scripts/scan_secrets.py <target>
21
21
  python <skill_dir>/scripts/check_gitignore.py <target>
22
22
  ```
23
23
 
24
- If Python is unavailable or a script fails, say so explicitly in the report ("automated secret scan could not run; manually reviewed instead") and do the equivalent manually: grep for key prefixes (`sk_live_`, `sk_test_`, `AIza`, `AKIA`, `ghp_`, `xox[bp]-`) and literal assignments to names containing `key`, `secret`, `token`, `password`.
24
+ If Python is unavailable or a script fails, say so explicitly in the report ("automated secret scan could not run; manually reviewed instead") and do the equivalent manually: grep for key prefixes (`sk-proj-`, `sk-ant-`, `gsk_`, `re_`, `sk_live_`, `sk_test_`, `AIza`, `AKIA`, `ghp_`, `xox[bp]-`), JWT tokens with `service_role`, database URIs, and literal assignments to names containing `key`, `secret`, `token`, `password`.
25
25
 
26
26
  ## Step 2 — Triage every script finding
27
27
 
28
28
  The scripts over-match on purpose. For each hit, open the file and decide:
29
29
 
30
- - **Live Stripe key (`sk_live_...`)** → Critical. Charges real cards. Recommend immediate rotation at dashboard.stripe.com, not just deletion.
31
- - **Test Stripe key (`sk_test_...`) in source** → Should Fix. Not production-critical but must not be committed; rotate if the repo was ever shared/pushed publicly.
32
- - **AWS `AKIA`, Google `AIza`, GitHub `ghp_`, Slack tokens in source** → Critical. Recommend revoking at the provider console.
33
- - **Publishable keys (`pk_live`, `pk_test`, Supabase anon keys, Firebase apiKey config)** → NOT findings. These are public-by-design; say so in one line so the user isn't confused.
30
+ - **OpenAI Project Keys (`sk-proj-...`, `sk-None-...`)** → **Critical**. Charges API accounts. Revoke immediately at platform.openai.com.
31
+ - **Anthropic Claude Keys (`sk-ant-api03-...`)** → **Critical**. Charges API usage. Revoke at console.anthropic.com.
32
+ - **Groq (`gsk_...`), Perplexity (`pplx-...`), HuggingFace (`hf_...`)** → **Critical**. Revoke at provider consoles.
33
+ - **Resend Email Keys (`re_...`)** → **Critical**. Used for phishing and mass spam abuse under your domain.
34
+ - **Supabase `service_role` JWT (containing `"role":"service_role"`)** → **Critical**. Completely bypasses Row-Level Security across all tables.
35
+ - **Database Connection URIs with passwords** (`postgres://...:...@...`, `mongodb+srv://...`) → **Critical**. Direct database access.
36
+ - **Live Stripe key (`sk_live_...`)** → **Critical**. Charges real cards. Recommend immediate rotation at dashboard.stripe.com.
37
+ - **Test Stripe key (`sk_test_...`) in source** → **Should Fix**. Must not be committed; rotate if repo was ever shared/pushed publicly.
38
+ - **AWS `AKIA`, Google `AIza`, GitHub `ghp_`, Slack tokens in source** → **Critical**.
39
+ - **Publishable keys (`pk_live`, `pk_test`, Supabase anon keys, Firebase apiKey config)** → **NOT findings**. These are public-by-design; note this distinction so the user isn't confused.
34
40
  - **Placeholders** (`your-api-key-here`, `<secret>`, dummy values) → not findings.
35
- - Anything inside test/fixture/mock directories → not findings (the scripts already skip these).
41
+ - Anything inside test/fixture/mock directories → not findings (scripts skip these).
36
42
 
37
43
  ## Step 3 — Client-exposure pass (Check 1b)
38
44
 
39
- Manually verify secrets aren't reachable from the browser:
45
+ Verify secrets aren't reachable from the browser:
40
46
 
41
47
  - Grep frontend code (`src/`, `app/`, `components/`, `pages/`, `public/`, client entry points) for references to secret env vars or service-role keys.
42
- - In Next.js: any secret used outside a server-only context, or a secret var incorrectly prefixed with `NEXT_PUBLIC_`. In Vite/CRA: secrets behind `VITE_*` / `REACT_APP_*` get bundled into shipped JS — Critical.
43
- - Supabase `service_role` key, Firebase admin SDK private key JSON, OpenAI/Stripe secret keys appearing anywhere client-reachable → Critical.
48
+ - **Bundler Prefixes:** In Next.js, Vite, CRA, Expo: any secret placed behind `NEXT_PUBLIC_*`, `VITE_*`, `REACT_APP_*`, `EXPO_PUBLIC_*` gets bundled into shipped browser JavaScript → **Critical**.
49
+ - **React Server Component (RSC) prop leaks:** In Next.js App Router, check if a Server Component imports a private secret and passes it as a prop to a client component (`<ClientComponent apiKey={process.env.PRIVATE_KEY} />`). Next.js serializes props into the client payload JSON → **Critical**.
50
+ - Supabase `service_role` key, Firebase admin SDK private key JSON, OpenAI/Stripe/Anthropic secret keys appearing anywhere client-reachable → **Critical**.
44
51
 
45
- ## Step 4 — .gitignore hygiene (Check 2)
52
+ ## Step 4 — .gitignore & Docker hygiene (Check 2)
46
53
 
47
54
  From `check_gitignore.py` output plus manual review:
48
55
 
49
- - `.env` / `.env.local` present but not ignored → Critical regardless of contents.
50
- - No `.gitignore` at all with secret files present → Critical.
51
- - Run `git log --all --full-history -- .env` (if git available). If `.env` was ever committed → Critical, and state plainly: removing it now is not enough; every secret in git history must be rotated because history stays recoverable.
56
+ - `.env`, `.env.local`, `.env.production` present but not ignored in `.gitignore` → **Critical** regardless of contents.
57
+ - **Docker risk:** If a `Dockerfile` exists and `.env` is omitted from `.dockerignore` → **Critical** (bakes secret environment files into public container image layers).
58
+ - **NPM auth tokens:** `.npmrc` files containing `_authToken=` committed in git → **Critical**.
59
+ - Run `git log --all --full-history -- .env` (if git available). If `.env` was ever committed → **Critical**, and state plainly: removing it now is not enough; every secret in git history must be rotated because git history remains permanently recoverable.
52
60
 
53
61
  ## Report
54
62
 
63
+ Save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory following the report structure in `SKILL.md`. Output the executive summary, key findings, and verdict in your conversation response, and include a reference to `checkmyvibe-report.md`.
55
64
  Use the format, severity rubric, and final-summary structure from SKILL.md. Scope reminder for this run: "secrets-only check — Checks 3 (auth), 4 (db), 5 (IDOR), 6 (inputs), and 7 (payments) were skipped. This does not mean the app is secure. Run a full `/checkmyvibe` audit before launch."
@@ -12,15 +12,16 @@ If it still cannot be found, tell the user and stop — do not improvise an audi
12
12
 
13
13
  Then read `SKILL.md` in full and run the **complete audit: Checks 1a, 1b, 2, 3, 4, 5, 6, and 7**:
14
14
 
15
- - Check 1a — server-side secrets and credentials
16
- - Check 1b — client-exposed secrets
17
- - Check 2 — .gitignore hygiene (including git-history check for committed `.env`)
18
- - Check 3 — missing or fake authentication
19
- - Check 4 — database / BaaS misconfiguration (Supabase RLS, Firebase rules, storage)
20
- - Check 5 — broken object-level authorization (IDOR/BOLA), route by route
21
- - Check 6 — unvalidated inputs, SQLi/XSS risk, mass assignment, missing rate limiting on auth endpoints
22
- - Check 7 — client-side payment/pricing logic AND webhook signature verification
23
-
24
- Run every script in the skill's `scripts/` folder that maps to Checks 1–4 (`scan_secrets.py`, `check_gitignore.py`, `check_auth_patterns.py`, `check_db_config.py`) against the target directory before relying on your own reasoning. If Python is unavailable or a script fails, state that explicitly in the report and do the check manually instead of silently skipping it.
25
-
15
+ - Check 1a — server-side secrets and credentials (OpenAI, Anthropic, Groq, Resend, Supabase service-role JWTs, database URIs, Stripe, cloud keys)
16
+ - Check 1b — client-exposed secrets & RSC server-to-client prop leaks
17
+ - Check 2 — .gitignore and .dockerignore hygiene (including git-history check for committed `.env` and `.npmrc`)
18
+ - Check 3 — missing or fake authentication (mock user returns, no-op `next()` stubs, Clerk matcher holes, NextAuth secrets, Supabase `getUser`)
19
+ - Check 4 — database misconfiguration (Supabase RLS, Firebase rules, Neon pooling/SSL, Prisma/Drizzle schema checks, public SQLite files, MongoDB injection)
20
+ - Check 5 — broken object-level authorization (IDOR/BOLA across REST routes, Next.js Server Actions, tRPC, and multi-tenant org boundaries)
21
+ - Check 6 — unvalidated inputs (SSRF in AI link/image scrapers, SQLi, NoSQL injection, DOM XSS in AI markdown, mass assignment, CORS wildcards, rate limiting)
22
+ - Check 7 — client-side payment logic, webhook signature verification (Stripe, Lemon Squeezy, Dodo Payments, Polar, Paddle, Razorpay), webhook idempotency, and subscription lifecycle handling
23
+
24
+ Run every script in the skill's `scripts/` folder (`scan_secrets.py`, `check_gitignore.py`, `check_auth_patterns.py`, `check_db_config.py`, `check_payment_config.py`) against the target directory before relying on your own reasoning. If Python is unavailable or a script fails, state that explicitly in the report and do the check manually instead of silently skipping it.
25
+
26
+ Save the complete, detailed audit report to `checkmyvibe-report.md` in the target directory following the report structure in `SKILL.md`. Output the executive summary, key findings, and verdict in your conversation response, and include a reference to `checkmyvibe-report.md`.
26
27
  Use the report format, severity rubric, evidence/confidence rules, post-fix verification step, and full-audit final summary structure defined in `SKILL.md`.