Cybersecurity Basics Every Developer Should Know


Security is not a feature you add at the end of a project. It’s a set of practices woven into every decision you make as a developer. I’ve seen too many applications go to production with easily preventable vulnerabilities. Here are the fundamentals that every developer should know, regardless of your role or seniority level.

Input Validation: Trust Nothing

Every piece of data that enters your application — from forms, URL parameters, HTTP headers, file uploads, API requests — must be validated and sanitised. This isn’t optional. It’s the single most effective defence against the majority of web vulnerabilities.

SQL Injection remains one of the most exploited vulnerabilities despite being entirely preventable. Never concatenate user input into SQL queries:

// DANGEROUS - never do this
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;

// SAFE - use parameterised queries
const query = 'SELECT * FROM users WHERE id = ?';
const user = await db.get(query, [req.params.id]);

Every database library and ORM supports parameterised queries. There is no excuse for writing raw string concatenation in SQL.

Cross-Site Scripting (XSS) occurs when user-supplied content is rendered as HTML without escaping. Modern frameworks handle this by default — React escapes JSX expressions, Vue escapes template interpolations — but the risk reappears when you use dangerouslySetInnerHTML or v-html. Use those features only with content you control or content that’s been sanitised with a library like DOMPurify.

Authentication Done Right

Hash passwords with bcrypt, scrypt, or Argon2. Never store passwords in plaintext, MD5, or SHA-256 without salt. These are broken for password storage and have been for years.

import bcrypt from 'bcrypt';

// Hashing
const hash = await bcrypt.hash(password, 12);

// Verification
const valid = await bcrypt.compare(inputPassword, storedHash);

The work factor (12 in this example) should be high enough that hashing takes around 250ms. This is intentionally slow — it makes brute force attacks impractical.

Use established authentication libraries rather than building your own. NextAuth (now Auth.js), Passport.js, Firebase Auth, or Clerk handle the edge cases that trip up custom implementations: session fixation, CSRF protection, token rotation, rate limiting on login attempts.

Implement rate limiting on authentication endpoints. Without it, attackers can try thousands of password combinations per minute. A simple rule like “5 failed attempts per IP per 15 minutes” stops most automated attacks.

Dependency Security

Your application’s dependencies are part of its attack surface. A vulnerability in a transitive dependency you’ve never heard of can compromise your entire application.

Run vulnerability scans regularly. npm audit, pip audit, bundler-audit — your package manager likely includes a vulnerability scanning tool. Run it in CI on every pull request.

Update dependencies promptly. When a security patch is released, apply it quickly. The window between a vulnerability disclosure and active exploitation is getting shorter. Automated dependency update tools (Dependabot, Renovate) help keep this manageable.

Review what you install. Before adding a new dependency, check its maintenance status, download count, and known vulnerabilities. A package with 50 weekly downloads and no updates in two years is a risk, regardless of how useful it seems.

HTTPS Everything

There’s no reason to serve anything over HTTP in 2026. Let’s Encrypt provides free TLS certificates. Cloudflare, Vercel, and Netlify provide HTTPS automatically. Even local development should use HTTPS to match production behaviour.

Set the Strict-Transport-Security header to ensure browsers always use HTTPS:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Set cookies with the Secure flag so they’re never sent over plain HTTP.

Security Headers

A few HTTP headers significantly improve your application’s security posture:

Content-Security-Policy: default-src 'self'; script-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()

Content-Security-Policy (CSP) prevents XSS by restricting which scripts can execute. Start with a strict policy and relax it as needed.

X-Content-Type-Options prevents browsers from MIME-sniffing responses, which can lead to script injection.

X-Frame-Options prevents clickjacking by blocking your site from being embedded in iframes.

Secrets Management

Never commit secrets to version control. API keys, database passwords, encryption keys — these belong in environment variables or a dedicated secrets manager, not in your code.

Use .gitignore to exclude .env files. Use pre-commit hooks with tools like TruffleHog or git-secrets to catch accidental commits before they happen.

If a secret is accidentally committed, rotating it immediately is not optional. Even if you force-push to remove the commit, the secret may already be cached by GitHub, scraped by bots, or present in someone’s local clone. One firm I talked to at team400.ai mentioned that credential exposure incidents are among the most common security issues they help Australian businesses remediate.

Logging and Monitoring

Log authentication events. Failed login attempts, password changes, permission changes — these are the events that matter most for detecting security incidents.

Never log sensitive data. Passwords, tokens, credit card numbers, and personally identifiable information should never appear in log files. It’s easy to accidentally log an entire request body that contains sensitive fields.

Set up alerts for unusual patterns. A sudden spike in failed login attempts, requests from unusual geographic locations, or API calls at unusual hours can indicate an active attack.

Keep Learning

Security is a moving target. New vulnerabilities are discovered constantly, and attack techniques evolve. Follow resources like the OWASP Top Ten, subscribe to security advisories for your framework and language, and consider periodic security audits.

You don’t need to be a security expert, but every developer needs to understand these fundamentals. The cost of prevention is always lower than the cost of a breach.