Home Projects Services Blog Contact
Back to Blog

5 security flaws every developer should know

Common mistakes that get web apps compromised, what they look like in code, and how to prevent each one.

TL;DR

SQL injection, XSS, broken authentication, sensitive data exposure and security misconfiguration keep showing up in real incidents. They're quick to understand, and fixing them early costs far less than dealing with a breach.

All five come from the OWASP Top 10, the reference list of web application security risks. In the 2021 edition, broken authentication appears as Identification and Authentication Failures, and sensitive data exposure as Cryptographic Failures. Check your own apps against them before an attacker does.

1. SQL injection

If your code builds SQL by concatenating user input into a string, an attacker can type SQL into a form field and change what the query does. Depending on the database permissions, that means reading, modifying or deleting the whole database. Parameterized queries fix this: the input is sent as data and is never interpreted as SQL.

❌ Vulnerable Code
# NEVER do this
query = f"SELECT * FROM users WHERE username = '{username}'"
# Attacker inputs: ' OR '1'='1
# Result: returns ALL users
✅ Safe Code (Parameterized Query)
# Always use parameterized queries
cursor.execute("SELECT * FROM users WHERE username = %s", [username])

# With Django ORM (automatically safe)
User.objects.filter(username=username)

2. XSS (cross-site scripting)

XSS happens when user input is rendered into a page as HTML instead of text. An attacker stores a script in a comment or a profile field, and it runs in the browser of everyone who opens that page. From there it can steal session cookies, send requests as the victim or rewrite the page.

❌ Vulnerable / ✅ Safe
// ❌ NEVER inject raw user content into HTML
element.innerHTML = userInput;

// ✅ SAFE: escape HTML entities
element.textContent = userInput;

// ✅ SAFE in React (automatic escaping)
return <div>{userInput}</div>;

// Django templates are safe by default
{{ user_input }}  {# Auto-escaped #}
{{ user_input|safe }}  {# Dangerous! Only use for trusted content #}

3. Broken authentication

Weak password rules, no rate limiting on the login endpoint, sessions that never expire, tokens stored where any injected script can read them (localStorage is the usual example). Each of these makes account takeover easier, and attackers often combine several.

Hash passwords with bcrypt or Argon2. Keep access tokens short-lived (around 15 minutes) and pair them with a longer refresh token (around 7 days). Rate limit login attempts, and serve everything over HTTPS.

4. Sensitive data exposure

Passwords written to logs in plain text. API keys committed to GitHub. Card numbers stored unencrypted. Secrets hardcoded in source files. Keep secrets in environment variables, keep .env files out of Git, and store as little sensitive data as you can.

✅ Secure Environment Handling
# .env file (NEVER commit this)
SECRET_KEY=your-secret-key
DATABASE_URL=postgresql://...
STRIPE_KEY=sk_live_...

# .gitignore: always include
.env
*.env
.env.local

# Load safely in Python
from decouple import config
SECRET_KEY = config('SECRET_KEY')

5. Security misconfiguration

DEBUG=True in production, default admin credentials, public S3 buckets, database ports open to the internet. These come up a lot on a developer's first VPS deployment, and they're easy to fix once you know to look for them.

Production checklist: DEBUG=False, a strong SECRET_KEY, ALLOWED_HOSTS set, HTTPS enforced, the admin URL moved from its default, and every port you don't need closed.

Make it a habit

Security is hard to bolt on at the end. It works better as a set of habits: parameterized queries, escaped output, sane authentication defaults, secrets kept out of the repo, a checklist before every production deploy. Get these five right and you've closed the holes attackers usually try first.

Tous les articles Article suivant