You’re building fast. You’re shipping daily. Security can’t slow you down—but getting hacked definitely will. Here’s the no-BS checklist for indie developers who want to ship secure code without the enterprise overhead.
Before You Write Code
Environment Setup
- Use
.envfiles for local secrets (never commit them) - Add
.envto.gitignorebefore first commit - Set up pre-commit hooks to catch secrets
# Install git-secrets
git secrets --install
git secrets --register-aws
Dependencies
- Use
npm auditoryarn auditin CI - Enable Dependabot or Renovate for auto-updates
- Lock dependency versions (
package-lock.json)
Authentication
Password Storage
- Use bcrypt or Argon2 (never MD5 or SHA1)
- Minimum 12 rounds for bcrypt
const bcrypt = require('bcrypt');
const saltRounds = 12;
const hash = await bcrypt.hash(password, saltRounds);
Session Management
- Secure, HttpOnly cookies
- Regenerate session ID on login
- Set reasonable expiration times
// Express session config
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JS access
sameSite: 'strict', // CSRF protection
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}
}));
OAuth / Social Login
- Use established libraries (Passport.js, NextAuth)
- Validate redirect URIs
- Store tokens securely
Input Handling
Validation
- Validate all input server-side (client validation is UX, not security)
- Use schema validation (Zod, Joi, Yup)
- Whitelist allowed values when possible
Output Encoding
- HTML encode user content before rendering
- Use framework’s built-in escaping
- Set Content-Type headers correctly
// React automatically escapes
<div>{userContent}</div> // Safe
// Dangerous - avoid unless necessary
<div dangerouslySetInnerHTML={{__html: userContent}} /> // XSS risk
Database
Queries
- Always use parameterized queries
- Never interpolate user input into SQL
- Use ORM for most operations
Access
- Database not exposed to internet
- Separate read/write users if possible
- Regular backups (test restore!)
API Security
Headers
- Set security headers
// Helmet.js for Express
app.use(helmet());
Rate Limiting
- Implement rate limiting on auth endpoints
- Consider stricter limits on expensive operations
CORS
- Whitelist specific origins
- Never use
origin: '*'with credentials
Infrastructure
HTTPS
- HTTPS everywhere (Let’s Encrypt is free)
- HSTS header enabled
- Redirect HTTP to HTTPS
Secrets Management
- Use environment variables (never hardcode)
- Different secrets per environment
- Rotate secrets periodically
Logging
- Log authentication events
- Never log passwords or tokens
- Set up alerts for suspicious activity
Deployment
Production Checklist
- Debug mode OFF
- Error messages don’t leak info
- Unnecessary ports closed
- Default credentials changed
- Admin panels protected
Monitoring
- Uptime monitoring
- Error tracking (Sentry, etc.)
- Basic security monitoring
Ongoing
Regular Tasks
- Weekly dependency updates
- Monthly security scan
- Quarterly secret rotation
- Annual security review
Incident Prep
- Know how to rotate all secrets
- Have a communication plan
- Back up your backups
The 80/20 Rule
If you only do five things:
- Use HTTPS everywhere
- Parameterize all queries
- Hash passwords with bcrypt
- Keep dependencies updated
- Run automated security scans
These five practices prevent 80% of common attacks.
Conclusion
Security doesn’t have to be complicated. Start with the basics, automate what you can, and add layers as you grow. The goal isn’t perfect security—it’s making yourself a harder target than the next guy.
Hacker Bot handles the monthly security scan for you. Set it up once, get notified when something’s wrong.