Secure coding
Designing applications so security is part of every feature and release.
Application security
I learned to begin with the data, users, trust boundaries, and failure paths. Input is validated at each server boundary, errors are useful without exposing internals, dependencies are reviewed, and every sensitive action has an explicit permission check.
Design questions
- What information enters, leaves, or persists?
- Who may perform each action and on which records?
- What happens when authentication, storage, or an integration fails?
Release evidence
- Threats and acceptance checks are written before implementation.
- Security-relevant code is reviewed and tested.
- Logs help investigate problems without recording secrets.
Identity, JWTs, hashing & user management
Authentication proves an identity; authorization decides what that identity may do. JWTs are short-lived signed credentials whose signature, issuer, audience, expiry, and algorithm must be checked. Passwords are protected with Argon2id or bcrypt and unique salts, while account roles follow least privilege and have a clear create, change, disable, and audit lifecycle.
Encryption and database management
TLS protects data in transit, encryption protects selected readable data at rest, and keys stay separate from the information they protect. Databases use restricted service accounts, reviewed migrations, parameterized queries, tested backups, and private network access. SQL injection is prevented by keeping commands separate from user-controlled data.
Hardening APIs
Every protected endpoint authenticates the caller and authorizes the exact object and action. APIs enforce schemas, size limits, safe errors, rate limits on sensitive routes, intentional CORS, minimal responses, and secrets supplied through protected runtime configuration.
A successful login never grants automatic access to every record. Authorization is checked again at each boundary.
Container permissions
Services run as non-root where practical, avoid privileged mode, mount only required paths, and join only intentional networks. Databases and management interfaces remain private by default. Containers improve isolation, but host patching, secret protection, backups, monitoring, and least privilege still matter.