Plan input validation
π¦Curated Cursor AI agent skills, slash commands, MCP configs, subagents & rules for full-stack dev β React 19, Next.js 15, Supabase, Tailwind v4, TypeScript
npx -y skills add kensaurus/cursor-kenji --skill plan-input-validationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Audit every trust boundary for unvalidated input, injection, and forged-request gaps, then produce a phased hardening plan. Use when the user says "validate my inputs", "is my app injection-safe", "check my forms", "XSS", "dangerouslySetInnerHTML", "my Stripe webhook", "can someone forge requests", or is hardening before launch. AI code has happy-path bias: missing Zod, dangerouslySetInnerHTML without DOMPurify, webhook signature gaps (empty or unchecked signing secrets), raw-body signature mistakes, missing idempotency. Stack-aware for Supabase, Stripe, Next.js. Plan only until each phase is approved. Pairs with plan-rls-audit, plan-security-audit, audit-fe-api. Do NOT use for row access (plan-rls-audit) or secrets (plan-secrets-audit).
The file declares its own license as MIT. That is the authorβs claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
6.6 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
Input-Validation & Trust-Boundary Audit + Hardening Plan
Role: Senior application security engineer (trust-boundary lens).
Task: Map every point untrusted data enters, score validate/sanitize/authenticate
gaps, phase remediations, emit plan-input-validation.md. Audit & plan only β no
code changes until each phase is approved.
Walk every boundary. Find what's trusted that shouldn't be. Change nothing until approved.
AI agents write code that works on the inputs you showed them. Two signature patterns
recur: dangerouslySetInnerHTML without DOMPurify (XSS), and webhook handlers without
real signature verification β the reported empty-signing-secret bypass class, where an
empty secret lets any attacker forge valid signatures and credit unlimited quota
without payment.
This skill is the audit-and-plan half. Execution goes to backend-patterns /
backend-error-handling / audit-security after you approve each phase.
When this fires
Trigger phrases: "validate my inputs", "is this injection-safe", "check my forms / API", "XSS", "dangerouslySetInnerHTML", "my Stripe webhook", "can requests be forged", "sanitize user content", "pre-launch input hardening".
Do not fire for: row-level access (plan-rls-audit), credential exposure
(plan-secrets-audit), or broad architecture review (plan-security-audit).
This skill owns the boundary where untrusted data enters.
The four boundary classes
1 Β· Form & API input
- No schema validation β bodies/params/query without Zod (or equivalent).
- Type-coerced trust β
Number(req.body.amount)with no bounds. - Missing field-level checks β email format, length caps, enum membership.
- Mass assignment β spreading
req.bodyinto DB insert/update (role,is_admin,credits). - SQL/RPC injection β string-interpolated queries or raw user input into SQL.
2 Β· Rendered untrusted content (XSS)
dangerouslySetInnerHTML/v-html/innerHTMLwithout DOMPurify.- URL/attribute injection β
javascript:URIs, unvalidated redirects. - Stored XSS β content saved now, rendered raw later.
3 Β· Webhooks & forged requests (Stripe-aware)
- Signature not verified β or verified against empty secret (empty-secret bypass class).
- Raw-body mistake β
JSON.stringify(req.body)instead of raw bytes. - No idempotency β Stripe at-least-once retries double-process.
- Cross-gateway trust β fulfilling without checking callback source.
- Missing timestamp tolerance β replay window open.
- Returns 500 not 400 on bad signature β infinite Stripe retries.
4 Β· File uploads & other boundaries
- No type/size/MIME validation; trusting client content-type.
- Path traversal in filenames; SSRF in user-supplied URLs.
- Concurrency β read-modify-write races without DB constraints.
Procedure
- Map boundaries. Enumerate every untrusted entry point. Skip absent ones.
- Test each. For every boundary: validated? sanitized? authenticated?
- Score. Severity = reachability Γ impact.
- Phase into shippable groups mapped to execution skills.
- Emit
plan-input-validation.md. End the turn. Do not edit code.
Guardrails
- Plan only. No Zod schemas, sanitizers, or webhook config changes.
- Validate at the boundary, not after.
- Signature β safety. Origin proof β safe to interpolate into SQL/HTML.
- Don't trust the client copy. Browser-only checks are UX, not security.
- Stack-specific raw-body note. Call out Next.js + Stripe raw-body requirement.
- Minimal quoting of source.
Report template β plan-input-validation.md
# Input-Validation & Trust-Boundary Audit β <repo>
_Audit-only. Nothing changes until each phase is approved._
## Scope
- Boundaries found: forms / API / webhooks / uploads / rendered content
- Stack: Supabase β Stripe β Next.js β | Assumptions: β¦
## Verdict
| Boundary class | Findings | Critical | Unauthenticated write reachable? |
|----------------|----------|----------|----------------------------------|
| Form & API | n | n | β¦ |
| Rendered (XSS) | n | n | β¦ |
| Webhooks | n | n | β¦ |
| Uploads/other | n | n | β¦ |
## Findings
| # | Boundary | path:line | Missing: validate/sanitize/authenticate | Sev | Direction |
|---|----------|-----------|-----------------------------------------|-----|-----------|
| I1 | Stripe webhook | api/webhooks/stripe.ts:12 | authenticate (no constructEvent) | Crit | verify raw body against secret; 400 on fail |
| I2 | comment render | Comment.tsx:30 | sanitize (dangerouslySetInnerHTML) | High | DOMPurify before render |
| I3 | profile update | actions/profile.ts:8 | validate (mass assignment) | High | Zod allowlist; drop role/credits |
## Phased burndown
- **Phase 1 β Forgeable money/data paths** β `backend-patterns` β webhooks, mass-assign
- **Phase 2 β XSS / rendered content** β `backend-error-handling` / `enhance-web-ux` β I2β¦
- **Phase 3 β Schema validation pass** β `backend-patterns` β Zod at every boundary
- **Phase 4 β Uploads & concurrency** β `audit-security` β files, races
## Execution handoff
Approve a phase to run it. Re-run after; for webhooks, verify with Stripe CLI
fixtures (real signed events) not mocked payloads.
Chains with
- Security spine β entry layer (this skill); data access:
plan-rls-audit; credentials:plan-secrets-audit. - Execution:
backend-patterns,backend-error-handling,audit-security,audit-fe-api. - Verify:
test-red-team+ Stripe CLI signed webhook fixtures.
Plan with a strong model; execute with
composer-2.5-execution.mdcriding along. The plan says which boundaries are open; the rule constrains how they're closed.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.