Why the OWASP Top 10 still matters
The OWASP Top 10 is a community-maintained ranking of the risks that actually break web applications, compiled from real vulnerability and breach data across thousands of organizations. It matters because the same categories keep causing incidents year after year: weak access control, injection, misconfiguration, and unpatched components. Treating the list as a checklist turns abstract security worry into a concrete set of things to verify on a schedule — before an attacker verifies them for you. What follows walks through the categories in plain language, each ending with the specific checks we run when we audit a client’s application.
Broken access control: the most common serious flaw
Access control failures top the list for a reason: they are easy to introduce and devastating in effect. The classic example is an application that checks whether you are logged in but not whether you are allowed to see the record you asked for — so changing /invoice/1041 to /invoice/1042 in the URL quietly shows you someone else’s invoice.
- Verify every sensitive action is authorized on the server, never only hidden in the interface.
- Log in as a low-privilege user and try changing IDs in URLs and API calls.
- Confirm sessions expire, rotate on login, and are invalidated on logout and password change.
- Deny by default: a new endpoint should require an explicit permission grant before it is reachable.
Authentication and cryptographic failures
Authentication failures are how attackers become someone else; cryptographic failures are how data leaks even when nobody logs in. The two meet at credential handling, which is where most small applications are weakest.
- Enforce multi-factor authentication for admin and financial access — it defeats most account-takeover attempts on its own.
- Rate-limit login attempts and alert on credential-stuffing patterns.
- Hash passwords with a modern algorithm (bcrypt, scrypt, or Argon2) — never MD5, SHA-1, or reversible encryption.
- Serve everything over TLS, encrypt sensitive data at rest, and keep secrets out of source control.
Injection and cross-site scripting
Injection is one of the oldest attacks on the web and it still works, because somewhere an application is still gluing user input into a query or a page. One unparameterized query is all it takes.
- Parameterize every database query — string-built SQL is never acceptable, including in reports and admin tools.
- Encode output by context (HTML, attribute, JavaScript) so user content cannot execute as script.
- Validate file uploads and anything passed to a shell, template engine, or LDAP query.
- Add a Content-Security-Policy header; it turns many cross-site-scripting bugs from exploitable into inert.
Insecure design and security misconfiguration
Some flaws cannot be patched because they were designed in: a password-reset flow that reveals whether an email address exists, an export feature with no rate limit, a trust relationship nobody wrote down. Misconfiguration is the operational sibling — the defaults you never changed.
- Threat-model new features before building: what would someone abuse this for?
- Turn off directory listings, sample apps, debug endpoints, and verbose error pages in production.
- Set the standard security headers (HSTS, X-Content-Type-Options, frame protections) and confirm them with a scanner rather than assuming.
- Review cloud storage permissions — publicly readable buckets remain a leading cause of large data exposures.
Vulnerable components and supply-chain integrity
A modern application is mostly other people’s code: frameworks, packages, build plugins, container images. Attackers know it, which is why known vulnerabilities in outdated components and tampered updates keep appearing on the list.
- Keep an inventory of third-party dependencies so you can answer “are we affected?” in minutes, not days.
- Patch on a schedule and subscribe to security advisories for your framework and runtime.
- Pin dependency versions and verify the integrity of build artifacts and CI plugins.
- Remove unused packages — every dependency you keep is attack surface you maintain.
Logging, monitoring, and server-side request forgery
Most breaches are discovered by someone outside the company, weeks late, because nothing inside was watching. Logging and monitoring turn a silent compromise into a detected incident. Server-side request forgery — tricking your server into fetching internal URLs on an attacker’s behalf — rounds out the list and is easy to check for.
- Log authentication events, permission failures, and changes to payment or contact details.
- Route alerts to a human who is expected to act, and test that path twice a year.
- Allow-list any URL your server fetches on a user’s behalf, and block internal address ranges from outbound server-side requests.
- Keep logs long enough to reconstruct an incident — thirty days is a floor, not a target.
How to make the checklist stick
A checklist run once is a snapshot; run quarterly, it is a security program. Put a recurring review on the calendar, give each category an owner, and record what was checked and what changed — the record itself becomes evidence for customer questionnaires and insurance renewals. For a small team without a security engineer, a quarterly self-check plus an independent review once a year covers most of the ground. That structure — scoped checks, findings ranked by risk, a written remediation plan — is exactly what our security audit engagements formalize, and this checklist is the technical core the reviews grew out of.
