# Skill: Run a security review covering the four basic holes before publishing a site > Before launching any web project, check for exposed secrets, unvalidated input, client-only permission checks, and verbose error leakage. Applies as a mandatory pre-publish step for any AI-generated site or app. Source: sodigi·learn — vibecoding/chtoby-ne-vzlomali · https://sodigi.io/learn/vibecoding/chtoby-ne-vzlomali ## When to use - You are about to push a project to a public git repository or deploy it to a live URL. - The project was generated by AI without an explicit security prompt. - The project accepts any user input (forms, file uploads, URL parameters). - The project calls paid external APIs or stores user data. ## Core rules - Secrets (API keys, DB passwords, tokens) must live in `.env.local` (or equivalent), never in source code. The `.env.local` file must be listed in `.gitignore`. - Validate all user input and file uploads server-side. Use a whitelist ("only these are allowed"), not a blacklist. For files: check size, MIME type, and extension separately. - Server-side permission checks must run before every sensitive action (delete, update, access to other users' data). Hiding a UI button is not protection. - Show users generic error messages ("something went wrong"). Send full error details only to server-side logs. Never log passwords, card numbers, tokens, or CVVs. - AI generates code that works by default, not code that is secure by default. Ask for security review explicitly every time. - Bots scan the entire internet automatically and find exposed keys within minutes of a public push. ## Procedure 1. Grep the codebase for hardcoded strings that look like keys, passwords, or tokens. Move any found to `.env.local`. Verify `.gitignore` includes `.env.local`. 2. Identify all user-input surfaces (forms, file uploads, query parameters). For each one, confirm server-side validation exists: type, format, length/size limits, extension whitelist for files. 3. Identify all sensitive server actions (delete, update, admin endpoints). Confirm each has a server-side authorization check that runs before the action, not just a hidden button in the UI. 4. Check error responses sent to users -- they must be generic. Check server logs -- they must not include secrets or PII. 5. Report all issues found in plain language with a suggested fix for each. ## Ready-to-use prompt ``` Run a security review of my project before publishing. Check against this checklist: 1. Secrets: are there any passwords, API keys, or tokens in the code? Everything must be in .env.local, and .env.local must be listed in .gitignore. 2. User input: is all input validated server-side? For file uploads, enforce size limit, allowed MIME types, and extension whitelist. 3. Permissions: before every sensitive action (delete, update, accessing other users' data), is there a server-side authorization check -- not just a hidden button? 4. Errors and logs: do users see only generic messages, and are passwords or card numbers absent from the logs? Report all problems found in plain words and suggest how to fix each one. ``` ## Pitfalls - "Nobody will attack my small site" -- bots scan everyone automatically regardless of size or traffic. - Storing API keys in source code and pushing to a public GitHub repo -- keys are found and abused within minutes. - Hiding a UI element and calling it security -- anyone who knows the URL bypasses the hidden button instantly. - Validating input only on the client (browser) -- easily bypassed; server-side validation is mandatory. - Showing full error text (file paths, stack traces, table names) to users -- these are a map for attackers. - Logging passwords or card numbers -- if the log file leaks, all credentials leak with it. - Publishing without running any security review -- a single checklist prompt catches most beginner holes at zero cost.