Install any skill in seconds. Free to start, no credit card required.
Get Started Free →RLS validation, security audits, OWASP compliance, and vulnerability scanning. Use when validating RLS policies, auditing API routes for auth, scanning for vulnerabilities, reviewing for exposed credentials, or performing pre-deployment security review. Do NOT use for routine feature development.
.claude/skills/bybren-llc-security-audit/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 143% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 21% | 0% |
| case-11 | ✗→✓ | ▲ Improved | -2% | 0% |
Guide security validation with RLS enforcement, OWASP compliance, and vulnerability detection following security-first architecture.
typescript// FORBIDDEN: Direct Prisma calls (bypass RLS) const users = await prisma.user.findMany(); // Must use: withUserContext, withAdminContext, or withSystemContext // FORBIDDEN: Missing authentication on protected routes export async function GET(req: Request) { // No auth check before accessing user data return getUserData(); } // FORBIDDEN: Exposed credentials const API_KEY = "sk_live_abc123"; // Hardcoded secret // FORBIDDEN: SQL injection vulnerability const query = `SELECT * FROM users WHERE id = ${userId}`; // Interpolated
typescript// CORRECT: RLS context wrapper const users = await withUserContext(prisma, userId, async (client) => { return client.user.findMany(); }); // CORRECT: Auth check before data access export async function GET(req: Request) { const { userId } = await auth(); if (!userId) { return new Response("Unauthorized", { status: 401 }); } return getUserData(userId); } // CORRECT: Environment variables for secrets const API_KEY = process.env.STRIPE_SECRET_KEY; // CORRECT: Parameterized queries const user = await prisma.$queryRaw`SELECT * FROM users WHERE id = ${userId}`;
bash# Find potential RLS bypasses grep -r "prisma\." --include="*.ts" app/ lib/ | grep -v "withUserContext\|withAdminContext\|withSystemContext"
bash# Find routes missing auth checks grep -r "export async function" --include="route.ts" app/ | head -20 # Manually verify each has auth check
bash# Scan for potential secrets grep -rE "(sk_live|pk_live|password|secret|key)" --include="*.ts" --include="*.tsx" | grep -v "process.env\|.env"
bash# Run security audit npm audit yarn audit # Check for high/critical vulnerabilities npm audit --audit-level=high
| Risk | Check | Status | | -------------------- | -------------------------------- | ------ | | A01 Broken Access | RLS enforced, auth on all routes | ☐ | | A02 Crypto Failures | Secrets in env vars only | ☐ | | A03 Injection | Parameterized queries, Zod | ☐ | | A04 Insecure Design | Auth-first pattern followed | ☐ | | A05 Misconfiguration | Prod env properly secured | ☐ | | A06 Vulnerable Deps | npm audit clean | ☐ | | A07 Auth Failures | Auth integration correct | ☐ | | A08 Data Integrity | RLS prevents tampering | ☐ | | A09 Logging Failures | Security events logged | ☐ | | A10 SSRF | External URLs validated | ☐ |
bash# Complete security check npm audit && yarn lint && echo "Security checks passed" # RLS bypass detection grep -r "prisma\." --include="*.ts" app/ lib/ | wc -l # Compare with context wrapper count # Secret detection git secrets --scan # If git-secrets installed grep -rE "sk_|pk_|password=" . --include="*.ts"
Before ANY production deployment:
markdown## Security Audit Report - {{TICKET_PREFIX}}-XXX ### Summary - **Date**: [date] - **Auditor**: Security Engineer - **Scope**: [what was audited] ### Findings | Severity | Issue | Location | Status | | -------- | ----- | -------- | ------ | | HIGH | ... | ... | FIXED | | MEDIUM | ... | ... | OPEN | ### RLS Validation - [x] All tables have RLS enabled - [x] User isolation verified - [x] Admin policies scoped correctly ### Recommendations 1. [recommendation] 2. [recommendation] ### Approval - [ ] Security Engineer approves - [ ] Ready for deployment
docs/guides/SECURITY_FIRST_ARCHITECTURE.mddocs/database/RLS_IMPLEMENTATION_GUIDE.mddocs/database/RLS_POLICY_CATALOG.md| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | fail→pass | 16,777 | 10,380 | -38% | 1 | 1 | 0% | 2,819 | 3,123 | +11% | 0 | 0 | — |
case-01 | fail→fail | 15,992 | 22,299 | +39% | 1 | 1 | 0% | 2,096 | 4,212 | +101% | 0 | 0 | — |
case-02 | fail→pass | 16,233 | 18,908 | +16% | 1 | 1 | 0% | 1,481 | 3,600 | +143% | 0 | 0 | — |
case-03 | fail→fail | 17,663 | 15,974 | -10% | 1 | 1 | 0% | 2,237 | 2,351 | +5% | 0 | 0 | — |
case-04 | fail→pass | 15,285 | 8,027 | -47% | 1 | 1 | 0% | 2,529 | 2,805 | +11% | 0 | 0 | — |
case-05 | fail→pass | 11,181 | 6,827 | -39% | 1 | 1 | 0% | 1,817 | 2,204 | +21% | 0 | 0 | — |
case-06 | pass→pass | 12,997 | 7,689 | -41% | 1 | 1 | 0% | 2,190 | 2,700 | +23% | 0 | 0 | — |
case-11 | fail→pass | 17,171 | 6,604 | -62% | 1 | 1 | 0% | 2,439 | 2,401 | -2% | 0 | 0 | — |
case-07 | pass→pass | 11,988 | 6,160 | -49% | 1 | 1 | 0% | 1,988 | 2,382 | +20% | 0 | 0 | — |
case-08 | pass→pass | 11,145 | 7,774 | -30% | 1 | 1 | 0% | 1,733 | 2,634 | +52% | 0 | 0 | — |
case-09 | fail→pass | 15,390 | 4,322 | -72% | 1 | 1 | 0% | 2,251 | 2,014 | -11% | 0 | 0 | — |
case-10 | pass→pass | 15,887 | 7,208 | -55% | 1 | 1 | 0% | 2,596 | 2,590 | -0% | 0 | 0 | — |
case-13 | fail→pass | 20,626 | 11,494 | -44% | 1 | 1 | 0% | 3,059 | 3,234 | +6% | 0 | 0 | — |
case-14 | fail→pass | 17,666 | 9,474 | -46% | 1 | 1 | 0% | 2,637 | 2,884 | +9% | 0 | 0 | — |
case-15 | fail→pass | 13,720 | 4,770 | -65% | 1 | 1 | 0% | 1,888 | 2,091 | +11% | 0 | 0 | — |
case-16 | pass→pass | 10,820 | 6,488 | -40% | 1 | 1 | 0% | 1,684 | 2,435 | +45% | 0 | 0 | — |
case-17 | fail→fail | 7,393 | 4,418 | -40% | 1 | 1 | 0% | 1,230 | 2,118 | +72% | 0 | 0 | — |
case-18 | pass→pass | 17,315 | 10,102 | -42% | 1 | 1 | 0% | 2,524 | 2,959 | +17% | 0 | 0 | — |
case-19 | fail→fail | 10,713 | 8,514 | -21% | 1 | 1 | 0% | 1,616 | 2,652 | +64% | 0 | 0 | — |
case-20 | fail→fail | 9,276 | 10,754 | +16% | 1 | 1 | 0% | 1,594 | 3,304 | +107% | 0 | 0 | — |
case-21 | pass→pass | 15,730 | 12,403 | -21% | 1 | 1 | 0% | 2,709 | 3,436 | +27% | 0 | 0 | — |
case-22 | pass→pass | 16,373 | 14,657 | -10% | 1 | 1 | 0% | 2,989 | 4,133 | +38% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +41 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.