The Developer's Security Checklist: 20 Things to Fix Before You Deploy
Most security breaches exploit known vulnerabilities that a checklist would have caught. Here are the 20 security checks every developer should run before shipping to production.

DevForge Team
AI Development Educators

The majority of security incidents involve vulnerabilities that were known, documented, and preventable. The OWASP Top 10 has looked largely the same for over a decade. Injection attacks, broken authentication, and exposed secrets keep showing up in breach reports because teams deploy without checking.
This checklist covers the 20 most common pre-deployment security failures. None of these require a security background — they require discipline.
Authentication and Authorization
1. Are passwords hashed with a modern algorithm?
If you're storing passwords, they must be hashed with bcrypt, scrypt, or Argon2. MD5, SHA-1, and SHA-256 are not appropriate for password storage — they're too fast and vulnerable to brute force. If you're using an authentication service like Supabase Auth or Auth0, this is handled for you.
2. Is there a rate limit on login attempts?
Unlimited login attempts enable credential stuffing and brute force attacks. Implement rate limiting at the authentication endpoint: 5-10 failed attempts per IP per 15 minutes is a reasonable starting point. Consider exponential backoff for repeated failures.
3. Are JWTs validated correctly?
If you're using JSON Web Tokens, verify that: the signature algorithm is RS256 or ES256 (not HS256 with a weak secret), the expiration time is checked, the audience and issuer claims are validated, and tokens cannot be used after logout (maintain a revocation list or use short expiration times).
4. Is authorization checked on every protected endpoint?
Authentication verifies who you are. Authorization verifies what you're allowed to do. Check that every API endpoint that returns or modifies user-specific data explicitly verifies that the authenticated user has permission to access that specific resource — not just that they're logged in.
5. Are admin routes protected separately from user routes?
Admin functionality should require explicit admin role verification, not just authentication. Test that a regular user token cannot access admin endpoints, even if they know the URL.
Input Validation and Injection Prevention
6. Is all user input validated server-side?
Client-side validation is a UX feature, not a security feature. Every input that reaches your server must be validated server-side. Use a schema validation library (Zod, Joi, Yup) to define what valid input looks like and reject anything that doesn't match.
7. Are database queries parameterized?
SQL injection remains the most common critical vulnerability. If you're writing raw SQL, every dynamic value must use parameterized queries — never string concatenation. If you're using an ORM, verify that dynamic conditions use the ORM's parameterization features and not raw query interpolation.
8. Is HTML output escaped to prevent XSS?
Any user-controlled content rendered as HTML must be escaped. In React, this is handled automatically when you render content as text nodes. It becomes a vulnerability when you use dangerouslySetInnerHTML, or when you're rendering markdown or rich text that includes HTML. Use a sanitization library (DOMPurify) before rendering HTML content from user input.
9. Are file uploads validated and stored safely?
If your application accepts file uploads: validate file type by content (MIME sniffing), not by extension; set a maximum file size limit; store files outside the web root or in object storage, not in a directory that's directly served by the web server; never execute uploaded files.
10. Is there protection against CSRF?
Cross-Site Request Forgery attacks trick a user's browser into making authenticated requests to your application from a malicious site. Use the SameSite=Strict or SameSite=Lax attribute on session cookies, and consider adding CSRF tokens for state-changing operations on cookie-authenticated endpoints.
Secret and Configuration Management
11. Are there any secrets in the codebase?
Run a secret scanning tool (GitGuardian, truffleHog, GitHub secret scanning) on your repository before every deployment. API keys, database credentials, and private keys should never appear in code or committed configuration files. Use environment variables or a secrets manager.
12. Are environment variables separated by environment?
Production secrets should not exist in development environments, and vice versa. Development API keys should have limited permissions. Audit which environments have access to production credentials.
13. Is the .env file in .gitignore?
Check your .gitignore file. The .env file should be listed. Run git log -- .env to verify that no previous version of the file was ever committed to git history. If it was, rotate all secrets immediately.
14. Are third-party API keys scoped with minimum permissions?
Every API key your application uses should have only the permissions it needs. A key that reads data should not have write permissions. A key used in a serverless function should not have admin access. Review the permission scopes on all external API integrations.
HTTPS and Transport Security
15. Is HTTPS enforced everywhere?
All traffic should be over HTTPS. Verify that HTTP requests are redirected to HTTPS (301 redirect, not 302). Set the Strict-Transport-Security header to tell browsers to always use HTTPS for your domain. If you have mixed content (HTTP resources loaded on an HTTPS page), fix it.
16. Are security headers set correctly?
Check that your application sets:
- Content-Security-Policy (restricts what resources can be loaded)
- X-Frame-Options: DENY (prevents clickjacking)
- X-Content-Type-Options: nosniff (prevents MIME sniffing)
- Referrer-Policy: strict-origin-when-cross-origin
Use securityheaders.com to scan your deployed application and get a grade.
Dependencies and Infrastructure
17. Are dependencies up to date?
Run npm audit (or the equivalent for your package manager) and address critical and high severity vulnerabilities before deploying. Outdated dependencies with known CVEs are a common attack vector. Configure automated dependency updates with Dependabot or Renovate.
18. Are error messages safe for production?
Development error messages often include stack traces, database query details, or internal file paths that help attackers understand your system. Verify that production error responses return generic error messages to users and log the details server-side only.
19. Is sensitive data excluded from logs?
Audit what your application logs. Passwords, payment card numbers, tokens, and personally identifiable information should never appear in log output. If your logging includes request/response bodies (useful for debugging), ensure those logs are scrubbed before production.
20. Is the attack surface minimized?
Disable or remove anything that isn't needed in production: debug endpoints, admin interfaces accessible from the public internet, unused API routes, test accounts, verbose error pages, and directory listing on your web server. Each unnecessary feature is a potential attack vector.
Running the Checklist
The 20 items above can be worked through in two to four hours before any production deployment. Most of them are one-time configurations that you verify rather than re-implement.
Build the checklist into your deployment process: either as a formal pre-deployment gate, a PR template checklist, or an automated security scan in your CI/CD pipeline. The tools that automate much of this (secret scanning, dependency auditing, security header checks) can run in under five minutes.
The cost of a security incident — in engineering time, customer trust, and potential liability — vastly exceeds the cost of the checklist. Run it every time.