I spent two years on a red team before moving to development. That experience fundamentally changed how I write code. Not because I learned fancy exploits, but because I learned to look at software the way attackers do – as a system with assumptions that can be broken.
The Attacker’s Mindset
Developers think: “What should this input be?” Attackers think: “What could this input be?” That shift in perspective is everything.
Every text field, API endpoint, file upload, and URL parameter is an entry point. The question isn’t whether someone will try to abuse it – it’s when.
Attack Vector 1: Input That Wasn’t Expected
You build a form that expects a name. Someone enters:
Robert'); DROP TABLE users;--
You build an image upload. Someone uploads a PHP file renamed to .jpg. You build a search field. Someone enters JavaScript that runs in every other user’s browser.
Defense: Never trust client-side input. Validate on the server. Use allowlists (what IS allowed) rather than blocklists (what ISN’T allowed). Use parameterized queries for databases.
Attack Vector 2: Broken Authentication
Common weaknesses attackers look for:
- Password reset tokens that don’t expire
- Session tokens that are predictable
- No rate limiting on login (brute force becomes trivial)
- Password stored as MD5 or SHA-1 (crackable in minutes)
- “Remember me” tokens stored in plain cookies
Defense: Use bcrypt or Argon2 for passwords. Implement account lockout after failed attempts. Generate cryptographically random session tokens. Set proper cookie flags (HttpOnly, Secure, SameSite).
Attack Vector 3: Exposed Information
You’d be shocked how much sensitive information leaks through:
- Error messages that reveal database structure
- API responses that include more data than the frontend needs
.gitfolders accessible on production servers- Environment files committed to public repositories
- Debug endpoints left enabled in production
Defense: Use generic error messages in production. Only return necessary fields in API responses. Add .git, .env, and debug endpoints to your server’s deny rules. Audit your public repos for accidentally committed secrets.
Attack Vector 4: Dependency Vulnerabilities
Your app might be secure, but what about your 847 npm dependencies? Supply chain attacks are becoming increasingly common. One compromised package can backdoor thousands of applications.
Defense: Run npm audit or pip audit regularly. Use Dependabot or Snyk for automatic vulnerability alerts. Pin dependency versions. Review changelogs before updating major versions.
A Simple Security Checklist
Before deploying anything, run through this:
- All user input is validated on the server
- SQL queries use parameterization
- Passwords are hashed with bcrypt/Argon2
- HTTPS is enforced everywhere
- Security headers are set (CSP, X-Frame-Options, etc.)
- Error messages don’t leak internal details
- Dependencies are up to date
- No secrets in source code
You don’t need to become a security expert. But thinking about these attack vectors while you code will make you a significantly better developer. The best code doesn’t just work – it works even when someone is actively trying to break it.
