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