Tags: web-dev concept

Common Vulnerabilities

Date: 2026-08-17


The handful that account for most real breaches, by mechanism rather than by acronym. Nearly all of them are one underlying error — data supplied by someone else being treated as instructions.


The unifying mechanism: untrusted input crossing into a context where it’s interpreted rather than displayed. Once you see that, the individual named attacks are variations on it.

Injection

Input becoming part of a command:

SQL INJECTION

query = "SELECT * FROM users WHERE
         email = '" + input + "'"

input:  ' OR '1'='1
result: ...WHERE email = '' OR '1'='1'
        → every user returned

input:  '; DROP TABLE users; --

The fix is parameterised queries, everywhere, without exception:

db.query(
  'SELECT * FROM users WHERE email = ?',
  [input]
)

Not escaping. Parameterisation. The value is sent separately from the statement, so it can never be parsed as SQL. Escaping is a filter you can get wrong; parameterisation removes the possibility.

The same shape recurs as command injection (input into a shell), LDAP injection, and NoSQL injection — a JSON body containing {"$ne": null} where a string was expected.

XSS — cross-site scripting

Input becoming part of the page:

STORED     saved, served to other users
           — a product review containing
             <script>
REFLECTED  echoed straight back from a
           query parameter
DOM-BASED  client-side JS writes untrusted
           data into the DOM
DANGEROUS              SAFE
el.innerHTML = input   el.textContent = input
document.write(input)  framework interpolation
eval(input)            — auto-escaped

What an XSS gets you: anything the user can do. Read their session, submit forms as them, read the DOM including card fields, exfiltrate whatever’s on screen. On a checkout page that is card-skimming, and it’s the mechanism behind most Magecart-style attacks.

Defences, layered:

1  escape on OUTPUT, per context
   (HTML, attribute, URL, JS string)
2  a framework that escapes by default
3  Content-Security-Policy as the
   backstop
4  HttpOnly cookies so a script can't
   read the session

Context matters. Escaping for HTML text is not sufficient inside an attribute or a URL — Reference - AEM covers the same idea as HTL’s display contexts.

CSRF — cross-site request forgery

Another site causing an authenticated request from your user’s browser:

On the attacker’s page:

<form action="https://shop/account"
      method="POST">
  <input name="email" value="attacker@x">
</form>
<script>form.submit()</script>

The browser attaches the victim’s cookies, and the request succeeds.

The cookie is the vulnerability — it’s sent automatically. Defences:

SameSite=Lax        the modern default;
                    covers most of it
CSRF token          per-session, verified
                    on state-changing
                    requests
check Origin        server-side

Broken access control

The most commonly found category, and the least technical:

GET /api/orders/1042
  → authenticated?  ✓
  → is it YOURS?    never checked

Change the number, read someone else’s order. Authentication passed; authorisation never happened — Authentication vs Authorisation.

SSRF — server-side request forgery

Your server fetching a URL an attacker supplies:

POST /import { "url": "..." }

attacker supplies:
  http://169.254.169.254/...
  → cloud metadata endpoint
  → credentials
  http://localhost:6379
  → internal Redis

Your server is inside the perimeter. Allow-list destinations, block private address ranges, and resolve then validate the IP — not just the hostname, or a DNS record that changes between check and fetch defeats it.

The rest, briefly

INSECURE DESERIALISATION   untrusted data
  turned into objects → code execution

SECURITY MISCONFIGURATION   default
  credentials, directory listing, verbose
  errors, an open admin path

VULNERABLE DEPENDENCIES     the code you
  didn't write. Most of your codebase

SENSITIVE DATA EXPOSURE     secrets in a
  repo, PII in logs, tokens in URLs

See: Dependency Management · Secrets Management

The habits that prevent most of it

  • Parameterise every query. No exceptions, no string building
  • Escape on output, in the right context. Let a framework do it
  • Validate input against an allow-list, not a block-list
  • Deny by default for authorisation, and check ownership per object
  • Ship a Content-Security-Policy. It converts many XSS bugs into non-events
  • Patch dependencies on a schedule, not when something breaks
  • Never put secrets in client code. Anything the browser holds is public