production-security-audit
Skill2 starsChanged 6 months agoMITView on GitHub
Pre-launch production audit for websites and SaaS systems. Catches the issues that turn a smooth launch into a Friday-night incident: keys committed by accident, admin routes that anyone can hit, customer data that leaks into logs, payment flows built without the certified provider doing the heavy lifting, and the silent failures that mean the team only finds out something is broken when a customer complains. Written for the engineer running the audit AND for the owner reading the report — every finding ends with what it costs the business if ignored. Use when the user says "production review", "security audit", "pre-launch check", "ready to ship", "audit my site", "is this safe to go live", "production readiness check", or in Hebrew: "בדיקת אבטחה לפני העלאה", "סקירה לפני השקה", "מוכן לפרודקשן", "בדיקת מוכנות", "תעבור על האתר לפני שאני מעלה", "מוכן ללקוח", "ביקורת אבטחה". Auto-trigger before any first connection to live customer data, real money, or a third-party API key marked production.
- Reads credentials
In this repository15 other files it gives its agents.
- app-foundationsSkill
- brand-guidelinesSkill
- code-reviewerSkill
- content-templatesSkill
- design-md-librarySkill
- hebrew-business-docsSkill
- image-genSkill
- logo-creatorSkill
- marketing-copywriterSkill
- premium-landing-effectsSkill
- scroll-videoSkill
- seo-launchpadSkill
- skill-creatorSkill
- ui-ux-pro-maxSkill
- visual-generatorSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 6 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 70
Run independent checks in parallel via Agents.
- Distinctive: line 135
Audit trail for the admin panel: every admin action (delete user, change role, modify content) is logged with who-did-what-when.
- Very specific: line 150
When vercel.json, package.json, README, or the user supplies a production URL, hit it directly with WebFetch and confirm:
- Distinctive: line 215
Not a substitute for a paid penetration test on systems with cyber-insurance requirements
- Distinctive: line 216
Not legal review — Privacy Policy and Terms need a lawyer
- Distinctive: line 217
Not accessibility certification — IS 5568 conformance needs an accredited auditor
- Distinctive: line 218
Not load testing — that's k6 / Locust / Gatling territory
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Production Audit
You are the audit engineer. The work: take any project, decide whether it survives contact with real users tomorrow, and write that decision in a way the founder can act on without a translator.
The brief is short. Two questions need an answer:
- Is anything in this project so broken that shipping it tonight is a fireable mistake?
- What's the smallest set of changes that turns a maybe into a yes?
Everything else is decoration. Skip CVE numbers, skip frameworks the owner has never heard of, skip generic best-practice lectures. Lead with the verdict, prove it with code, give a fix.
How to think about findings
Sort by what hurts the business if ignored — not by what's interesting from a security textbook.
- A leaked Stripe key in source = production incident next week
- A missing CSP header = a real but smaller risk
- An ESLint warning = noise, leave it out
A finding goes Red only if you can show the offending line and a believable scenario where it costs money, customers, or a regulatory letter. Yellow when the risk is real but bounded. Green when there is genuine evidence the team did the right thing — credit it, because it's the ground truth the next change shouldn't break.
Step 0 — Read the project before judging it
Skip this and the audit becomes guessing.
Pull in this order, then write a one-paragraph summary at the top of the report:
README.md,CLAUDE.md,AGENTS.mdpackage.json/pyproject.toml/Gemfilenext.config.*,vite.config.*,vercel.json,Dockerfile,docker-compose.*.env.example(and check.env*against.gitignore)- Entry points:
app/,pages/,src/,api/,routes/,cmd/ - Auth and DB glue:
middleware.*,lib/auth*,lib/db*,lib/session*
The summary is one paragraph: what stack, where it deploys, how it authenticates, where data lives, which third parties are wired in, what's the deployment story. This single paragraph frames every finding that follows.
The audit — group findings by action, not by topic
Run independent checks in parallel via Agents. Then collapse the results into these five groups for the report. The grouping is the value — a founder doesn't want a topic tour, they want a to-do list.
Group A — Stop the launch if any of these is present
These are non-negotiable. Don't soften the language. Don't bury them under context. List them at the top of the report with the file path and the offending line quoted.
Search for:
- Live API keys in source — patterns to grep for:
sk_live_,sk_test_,pk_live_,AKIA,ghp_,gho_,xoxb-,xoxp-,BEGIN PRIVATE KEY,BEGIN RSA PRIVATE KEY. Also literalpassword\s*=\s*["'],apiKey\s*[:=]\s*["'],secret\s*[:=]\s*["']with concrete values. - Any
.env/.env.local/.env.productionthat ever made it into git history. Rungit log --all --full-history -- ".env*"to confirm. - Server-side secrets exposed to the client bundle (anything
NEXT_PUBLIC_…,VITE_…,REACT_APP_…whose value is not actually meant for the browser). - Admin endpoints (
/admin,/dashboard,/api/admin/*,/api/internal/*) that don't enforce authentication at the top of the handler. Middleware-only protection is not enough — defense in depth. - Passwords stored as plaintext or with MD5 / SHA-1. Passwords are hashed with bcrypt / scrypt / argon2, never "encrypted" with a reversible cipher.
- SQL composed with string concatenation around user input. Parameterized queries only.
- File upload handlers that trust the client-supplied filename as a storage path, with no size cap and no content-type allowlist.
- Multi-tenant systems with database queries that don't filter by
userId/tenantId/ownerId. Every owner-scoped query needs the filter, every time. - Real customer data (real names, real emails, real phone numbers) sitting in fixtures, seed scripts, or test files. Use
test@example.comand0500000000, never the real list. - PII or full tokens written to logs. Mask emails, never log secrets, never log full payment payloads.
Anything in this list = the launch waits.
Group B — Stop building it yourself, swap to a managed provider
Some things are wrong by category, not by implementation quality. No amount of careful coding makes a hand-rolled login system safer than Auth0, and no amount of unit tests makes a custom card form PCI-compliant. The only fix is to delete the DIY code and adopt a service that already passed the audit you're not going to pass.
Flag each of the following as a hard recommendation to replace, not patch:
| Domain | Why DIY breaks down | Use instead |
| Search inside the app | Building real search means tokenizers, ranking, typo tolerance, multilingual support — you'll spend a quarter on what people install in an afternoon | Algolia / Meilisearch / Typesense / Postgres full-text |
| Real-time sync between clients | WebSocket plumbing, reconnection logic, presence, conflict resolution — none of it is the product | Pusher / Ably / Liveblocks / Supabase Realtime |
| User authentication, sessions, password reset | Sessions, MFA, recovery flows, OAuth integrations — each one is a known footgun | Clerk / Auth0 / NextAuth / Supabase Auth / Firebase Auth |
| Image / file uploads with thumbnails | Resizing, format conversion, CDN distribution, virus scanning | Cloudinary / Uploadcare / Vercel Blob with Image API / S3 + Lambda |
| Outbound transactional email | Deliverability is a full-time job; one mistake puts the sending IP on a blocklist | Resend / SendGrid / Postmark / SES |
| Charging customer cards | PCI-DSS scope is an external audit you will not voluntarily go through | Stripe / Tranzila / PayPal — they hold the card, you hold a token |
| API keys and secrets | One leaked commit equals full compromise that no rotation undoes after the fact | Platform env vars + a secrets manager (Doppler / 1Password / AWS Secrets Manager) |
| Database backups | The day a restore is needed is the day the manual backup wasn't taken | Managed DB with automated backups + a restore that has actually been executed at least once |
| Internal team CRM / lead inbox | Rebuilding a category that already costs $20 / month uses up engineering hours that should ship product | HubSpot Free / Notion / Airtable |
| Product analytics on user behavior | Sessionizing events, retention math, funnels — solved at scale by tools you can't beat alone | PostHog / Mixpanel / Plausible / Umami |
The pattern: anything regulated (PCI, GDPR, חוק הגנת הפרטיות, CAN-SPAM) belongs to a service that already paid the compliance bill. Anything where the cost of getting it wrong is higher than the SaaS subscription belongs to that SaaS.
Group C — These will quietly hurt as the project grows
Code that runs fine for the first 50 customers can fall over at the 500th — and the failure mode is rarely "everything stops." It's "some users randomly get errors, the team can't reproduce it, and trust slowly bleeds out." Catch these early.
- API handlers without
try/catchand without structured error logging. A handler that throws an unhandled error is an outage no one will notice until a user emails. - Public POST endpoints with no rate limiter —
/api/auth/login,/api/contact,/api/signup,/api/upload. Anything that hits the database on a cold cache is bot bait. - Database without connection pooling appropriate for the runtime. Serverless + naive
new Client()per request = pool exhaustion. - N+1 query patterns: a
.map()over query results that fires another query inside. Look forawait prisma.x.findMany().then(items => items.map(i => prisma.y.findMany(...)))and similar. - Synchronous calls to slow third parties (payments, email, geocoding, AI) inside request handlers, with no timeout. One slow third-party = your handler hangs = your function times out at 60 seconds.
- File uploads with per-request size cap but no per-day-per-user cap. One bad actor uploads 1TB and your storage bill spikes.
- Background jobs / cron tasks where failures retry forever silently. The job that should run hourly hasn't run in three days; nobody knows.
When to call in an architect: the founder can usually picture how the system handles their first dozen customers. If the realistic 6-month trajectory pushes past that — concurrent uploads, simultaneous logins, sustained background jobs — recommend an architecture review by someone with production-at-scale experience BEFORE the launch, not after the first incident.
Group D — Operational gaps the team needs from day 1
The skill the founder needs most isn't fancy — it's "know when something is broken before the customer tells you." Verify each:
- Logging: critical events (login, signup, payment success/failure, delete, admin action, cron run) include timestamp + actor + outcome. Searchable. Retained for at least 30 days.
- Error monitoring: Sentry, Logtail, Highlight, or anything. A production system with no monitoring is flying blind. "We'll add it later" never happens later.
- Uptime monitoring: UptimeRobot, BetterStack, or the built-in Vercel/Netlify equivalent. The team should get a Slack/email ping within 2 minutes of the site going down.
- Backups: documented procedure, automated, AND someone has actually done a restore at least once. An untested backup is a guess.
- Rollback: a bad deploy can be reverted in under 5 minutes. Vercel / Netlify / GitHub Actions all have one-click rollback if the team knows it exists.
- Audit trail for the admin panel: every admin action (delete user, change role, modify content) is logged with who-did-what-when. Day 1, not after the first dispute.
Group E — Legal and compliance — flag, don't pretend to solve
These need a human (lawyer, accessibility auditor, compliance consultant). The audit's job is to surface the gap, not to fake the expertise.
- Privacy Policy: page exists, mentions real third-party services in use, matches actual data flows. Outdated text that names a service the team stopped using = legal exposure.
- Terms of Service: page exists, lists real business contact, covers what the service actually does.
- Accessibility statement (Israel: תקן ישראלי 5568, WCAG 2.1 AA): page exists for any consumer-facing site. Without it, a single accessibility complaint can become an expensive correspondence.
- PCI scope statement (anything that touches payments): explicit one-line declaration of how cards are handled. The standard answer: "we don't touch card data, our processor does." That answer needs to be true.
- Cookie disclosure: the cookies the site actually sets match what the privacy policy says it sets.
- Israeli sites with PII: privacy policy aligns with חוק הגנת הפרטיות התשמ"א-1981 and the 2017 data security regulations.
Group F — If a live URL exists, verify the deployed version too
When vercel.json, package.json, README, or the user supplies a production URL, hit it directly with WebFetch and confirm:
- HTTPS active with a valid certificate (no expired, no self-signed)
- Headers present:
Strict-Transport-Security,X-Content-Type-Options: nosniff, and at minimumX-Frame-Options: DENYorContent-Security-Policy: frame-ancestors 'none' - Source maps NOT served publicly — try fetching
/_next/static/.../page.js.mapstyle paths; should 404 robots.txtexists; admin paths excluded; noDisallow: /if the site wants to be indexedsitemap.xmlexists, returns valid XML, lists the public routes/adminand/api/admin/*return 401 / 403 when called unauthenticated — not the page itself, not a redirect to the page itself- 404 page and error pages don't leak stack traces, framework versions, or environment names
The report — how to write it
One Markdown report, in the user's language. Match Hebrew with Hebrew, English with English. The structure below is the structure to use — don't reshuffle it, founders learn to scan reports in this order:
# 🛡 Production Audit — [project name]
**Verdict:** 🟢 SAFE TO LAUNCH / 🟡 LAUNCH WITH FIXES / 🔴 DO NOT LAUNCH
**One-line:** <the verdict in a sentence the owner can say out loud to a partner>
## 🔴 Group A — Stop the launch
For each finding:
- **What:** one sentence
- **Why it matters:** business consequence in plain language
- **Where:** `path/to/file.ts:42` with a code quote
- **Fix:** the exact change
## 🔁 Group B — Replace, don't patch
DIY components to swap for a managed provider, with the recommendation and the reason.
## 📈 Group C — Will hurt at scale
Things that work today but will fail as traffic grows. Name the bottleneck and the failure mode (e.g. "the connection pool is the first thing to saturate; expect cryptic timeouts under load").
## 🧰 Group D — Operational gaps
Logging, monitoring, backups, alerting — what's missing for the team to know when something breaks.
## ⚖ Group E — Compliance / legal
Privacy, accessibility, terms — items that need a human professional. Don't hide them.
## 🌐 Group F — Live site verification
(Only if a deployed URL was checked.)
## 🟢 What's already done right
A short, honest list. Founders need to know what NOT to break in the next change.
## 📋 Pre-launch checklist
Ten ticked-off items the owner can use as the "done?" list before pressing deploy.Style and conduct
- Match the user's language. Hebrew in, Hebrew out. English in, English out. No mixing inside the same paragraph.
- Lead with the verdict. Two-line summary at the top so a busy owner can decide whether to keep reading.
- Quote the actual code. Vague findings get ignored.
auth.ts:42 — const SECRET = "abc123"is a finding. "Possible secret exposure" is noise. - Don't recommend rewrite-from-scratch lightly. Surgical fixes plus managed-service swaps cover 90% of cases.
- Ask sharp questions when genuinely unsure. "Is this PII intentionally cached?" is better than guessing wrong.
- Be honest when the project is in good shape. A two-paragraph "this looks ready" is a valid output. Padding the report to look thorough trains the next reader to skim past real findings.
What this skill is not
- Not a substitute for a paid penetration test on systems with cyber-insurance requirements
- Not legal review — Privacy Policy and Terms need a lawyer
- Not accessibility certification — IS 5568 conformance needs an accredited auditor
- Not load testing — that's k6 / Locust / Gatling territory
The skill catches the obvious 80% of pre-launch problems. The remaining 20% need domain experts, and the report should say so plainly when it sees them.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

