Security topics
Browse by group, filtered for your role
Server-side
13Server-side flaws — where most real damage happens
Access control is the part that answers "what may THIS user do to THIS object". A broken access control bug is when the system already knows who you are (authentication succeeded) but never checks whether you are allowed. IDOR/BOLA is the common form: change `id=42` to `id=43` and read someone else's data.
API security is the set of flaws that appear because an API **has no UI to hide behind**. In a server-rendered application the UI decides what the user sees; in an API every endpoint is public surface and the client is just one of many callers. The OWASP API Security Top 10 is the catalogue of this family.
Authentication is the part that answers "is this person who they claim to be". Authentication vulnerabilities are the ways an attacker gets past that step without the right credentials: mass password guessing, skipping a step, reusing leaked credentials, or exploiting the side flows (password reset, "remember me").
A business logic flaw is when the attacker uses a feature **exactly as written**, in a way the designer never planned for. There is no payload, no special character, nothing to escape — just a sequence of legitimate operations reaching a wrong outcome.
Command injection is when user input reaches a shell command and the shell reads it as SYNTAX rather than as an argument. `;`, `|`, `&&`, `$(...)`, backticks and newlines are all shell operators, so a string containing them stops being one argument and becomes a second command.
File upload vulnerabilities are what happens when the server trusts what the client says about a file: the filename, the extension, the `Content-Type`. The attacker chooses all three. The worst outcome is **code execution**: an `.aspx`/`.php`/`.jsp` file landing in a directory the web server will execute, then fetched by URL.
Information disclosure is the application revealing what an attacker needs for the next step: stack traces, framework versions, internal paths, table names, an API key in a JavaScript bundle, or merely the **difference** between two error messages. It is rarely the incident itself; it is step one of every other incident.
Path traversal is when a user-supplied filename is joined into a filesystem path without validation, so `../` walks the read or write outside the intended directory. The classic outcome is reading `/etc/passwd`, `web.config`, `.env` or an SSH key — and in its write form it is arbitrary file overwrite, which is code execution.
A race condition is when two concurrent requests read the same stale state and both act on it. The classic shape is **check-then-act** (TOCTOU): both requests see "the discount code is still valid", both apply it, and the code redeems twice. There is no payload — only timing.
SQL injection happens when user-supplied data is concatenated into a query as SYNTAX rather than as data. The attacker then changes not just the search value but the statement itself: adding conditions, joining other tables, or running a second statement. NoSQL injection is the same bug one layer over — instead of a SQL string, the attacker sends an *operator object* that the driver interprets as query structure.
SSRF is a flaw that lets an attacker choose where your server sends an HTTP request. The application takes a URL from the user — to fetch a link preview, call a webhook, import data — and fetches it. Because the request originates INSIDE your trusted network, it reaches things the attacker cannot reach from the internet.
Cache deception is the reverse of cache poisoning: instead of poisoning a public page, the attacker tricks the cache into **storing the victim's PRIVATE page** (an account page, personal data) and then reads it. The mechanism is the cache and the server disagreeing about "is this URL a static resource or a dynamic one".
XXE is when an XML parser processes **external entities** — a feature of the XML standard letting a document declare "substitute the contents of that file or URL here". The attacker uploads XML declaring an entity pointing at `/etc/passwd` or `http://169.254.169.254/`, and the parser fetches it for them.
Client-side
7The browser is a hostile environment
Clickjacking is your page loaded inside a **transparent** iframe on the attacker's page, layered over decoy content. The user believes they are clicking the attacker's button, but the real click lands on your page — carrying their full session.
A Content Security Policy is a header telling the browser **which scripts may run** on your page. It does not fix XSS — it converts "the attacker injected code and it ran" into "the attacker injected HTML that does nothing". This is defence in depth, not a fix.
CORS is the mechanism that lets a page read a response from another origin — it **relaxes** the same-origin policy, it does not tighten it. A CORS misconfiguration means you have allowed an attacker's page to read your users' data, using their own session.
XSS is when user-controlled data is interpreted by the browser as CODE rather than content. The attacker's script runs in your origin, so it has everything your own JavaScript has: non-HttpOnly cookies, tokens in localStorage, and the ability to send requests already carrying the victim's session.
CSRF is when another website makes the victim's browser send a state-changing request to your application. The browser **attaches cookies automatically** to requests bound for that domain, so the request arrives with the victim's full session even though it originated on an entirely different page.
A DOM-based vulnerability is when the page's own JavaScript takes data from an attacker-controlled **source** (the URL, `location.hash`, `postMessage`, `localStorage`) and passes it to a dangerous **sink** (`innerHTML`, `eval`, `location`) — all in the browser, never touching the server.
A WebSocket opens a long-lived, two-way channel between the browser and the server. The core security problem is that the WebSocket handshake is **not constrained by the same-origin policy the way fetch/XHR is** and **the browser attaches cookies automatically** — so if the server does not check `Origin` itself, another page can open a connection carrying the victim's session (CSWSH).
Advanced & protocol
10Protocols, deserialization, LLM — the hardest group
GraphQL is a query layer that lets the client choose the shape of the data it receives. The security problems come from that flexibility: **the client decides the query**, so the attack surface is the whole graph — not a fixed set of endpoints — and authorisation and resource limits must be applied at the field level, not the route level.
A Host header attack is when the application trusts the `Host` header value (or `X-Forwarded-Host`) — a value the client sends and the attacker changes freely — and uses it to build URLs, select configuration, or route. The typical outcomes are password-reset poisoning (the reset link points at the attacker's domain) and cache poisoning.
HTTP request smuggling is when two servers on the same path — usually a reverse proxy or CDN in front and a backend behind — **disagree on where one request ends**. The attacker exploits that disagreement to smuggle the start of a second request into the tail of the first, and the backend treats it as a separate request — but attached to the next user's connection.
Insecure deserialization is an application rebuilding objects from untrusted data. The problem is not the data — it is that **the attacker chooses which classes get constructed**. Picking the right class already on the classpath is code execution, with no other vulnerability needed.
A JWT is a **self-describing** token: it carries both the data (claims) and how it was signed (the `alg` header). That is the problem — a token that states how to verify itself can also lie about it, and most JWT vulnerabilities are a library **trusting the token's header** instead of your configuration.
OAuth 2.0 is an **authorisation** protocol — it grants an application access to resources on a user's behalf. OpenID Connect (OIDC) is an **authentication** layer on top of OAuth that answers "who is this person". Most vulnerabilities come from using OAuth (authorisation) as if it were authentication, and from omitting checks the protocol requires but cannot enforce.
Prototype pollution is a JavaScript-specific flaw: the attacker sets a property on `Object.prototype` — the prototype shared by EVERY object — so a field they inject appears on every object in the application. The entry point is usually a recursive merge/clone/set-path function accepting a `__proto__` key from user data.
SSTI is when user input reaches the **template** rather than the data a template renders. A template engine is designed to run code — loops, conditionals, property access — so a user string that becomes template code is code execution, usually all the way to RCE.
Cache poisoning is when an attacker makes a cache (a CDN, a reverse proxy) store a malicious response, which the cache then serves to every subsequent user. The root mechanism is that **the cache key omits an input the response ACTUALLY depends on** — so two requests "identical to the cache" produce two different responses, and the malicious one gets stored.
Web LLM attacks are the family that appears when an application puts a language model in the loop: it takes user input, concatenates it into a prompt, and lets the model call tools or read data. The root problem is that **the model cannot distinguish your instructions from the attacker's data** — to it, both are just text in the same context window.
SDLC & supply chain
7Not covered by PortSwigger. Developers need it daily
Are you sure the image running in prod is the image you built?
The pipeline can deploy to prod. Whoever can edit the pipeline can edit prod.
Most of the code you ship you did not write. A03 is a brand-new Top 10:2025 category.
Secrets in env show up in `docker inspect`, `/proc`, and crash logs.
The closest thing to the real job: read the diff, flag the line, and do not cry wolf.
Read the standard like an auditor: if I had to answer yes or no to this requirement, could I?
The only topic that is core for all five roles, because it is a group activity, not an individual skill.
Cryptography & data
5Crypto used wrong is worse than no crypto
Encryption is not a switch. The real question is: where is the key and who can read it?
A key you cannot rotate is a key that will never be rotated.
Argon2id, not SHA-256. And if you can go passwordless, storing nothing is best.
Data you never store is data that cannot leak.
HSTS, minimum versions, chain validity, and the expiry date nobody is watching.
Infrastructure & runtime
6Where the last line of defence lives
Non-root, read-only rootfs, drop ALL capabilities — three config lines that stop most escalation paths.
A10 is new in Top 10:2025 and easy to dismiss: when an external API times out, does your code fail open or fail closed?
Pod Security Standards, default-deny NetworkPolicy, minimal RBAC. Over-privileged service accounts are the most common flaw.
Logs nobody reads are the same as no logs. The CTO question: would we know we were under attack?
Egress deny-by-default turns SSRF from an incident into a log line.
Not about DDoS — about one legitimate user doing a legitimate thing a million times.
Personal digital safety
3For everyday users — kept separate from AppSec content
SMS is the weakest second factor. Passkeys are the strongest.
A strong password you can remember is not strong. Use a password manager.
Not about spotting bad emails — about having a habit of checking before you click.