Application Security: The Most Common Issues We Find in Real Projects
The security problems that actually show up in commercial web projects — from the OWASP Top 10 to frontend-specific mistakes — and the practical fixes that prevent most of them.
Most security incidents in commercial web projects do not come from a novel attack — they come from a handful of well-known mistakes that keep recurring because they are easy to introduce and easy to overlook in review. This is the list we actually find during audits, roughly ordered by how often we see each one.
Where most real issues come from
| Issue | Typical cause | Impact |
|---|---|---|
| Broken access control | Missing server-side authorization checks | Data exposure/modification by unauthorized users |
| Injection (SQL, NoSQL, command) | Unsanitized input reaching a query/command | Data breach, full compromise |
| Cross-site scripting (XSS) | Unescaped user content rendered as HTML | Session hijack, account takeover |
| Secrets in client code or repos | API keys/tokens committed or bundled client-side | Unauthorized API access, cost abuse |
| Outdated dependencies | No routine update/audit process | Known, public exploits become viable |
| Insecure direct object references | Trusting a client-supplied ID without ownership check | Access to other users' data |
1. Broken access control
The single most common finding in real audits: an API endpoint checks that a user is logged in, but not that they own the resource they are requesting. Every authorization check has to happen server-side, on every request — a hidden button or a disabled UI element is not a security control, only a UX one.
2. Injection
Still on the OWASP Top 10 after two decades because string-concatenated queries keep getting written under time pressure. Parameterized queries and an ORM that escapes by default eliminate this category almost entirely — the fix is not vigilance, it is tooling that makes the unsafe pattern harder to write than the safe one.
3. Cross-site scripting (XSS)
Modern frameworks (React, Vue) escape output by default, which has quietly eliminated most classic XSS — until a developer reaches for `dangerouslySetInnerHTML` or `v-html` for a rich-text field and reintroduces the exact hole the framework was preventing. Any raw HTML rendering needs a sanitization library, not trust in the source.
4. Secrets in client code or version control
API keys and tokens committed to a repo, or bundled into client-side JavaScript where anyone can read them from devtools, is a recurring finding even on otherwise well-run projects. Secrets belong in environment variables on the server, never in anything shipped to the browser or committed to git — and a leaked secret needs immediate rotation, not just removal from the latest commit.
5. Outdated dependencies with known vulnerabilities
A vulnerable transitive dependency three levels deep is invisible without tooling and routine review. Automated dependency scanning (Dependabot, npm audit, or equivalent) in CI, with a real process for triaging and patching what it finds, closes most of this gap — leaving it unmonitored is the actual failure, not any single vulnerable package.
6. Insecure direct object references (IDOR)
Trusting a client-supplied ID (`/api/invoices/1234`) without verifying the requesting user actually owns that resource lets an attacker simply increment the number. Every resource-fetching endpoint needs an ownership or permission check, not just an authentication check.
What actually prevents these
- Authorization checks on every server-side request — never inferred from the UI.
- Parameterized queries and an ORM by default; raw query strings as a reviewed exception, not the norm.
- A sanitization library for any raw HTML rendering, with framework auto-escaping left on everywhere else.
- Secrets only in server-side environment variables, never in client bundles or git history.
- Automated dependency scanning wired into CI, with an actual triage process for what it flags.
- Security review as a normal part of code review for anything touching auth, data access, or user input — not a separate audit done once.
The bottom line
Application security is mostly discipline around a known, short list of recurring mistakes — not a constant arms race against novel threats. The fixes are largely process and tooling (parameterized queries, dependency scanning, server-side authorization) rather than heroics, which is exactly why they belong in the default engineering process on every engagement, not bolted on before a compliance audit.
Frequently asked questions
What is the most common security mistake in web applications?
Broken access control — checking that a user is authenticated but not that they are authorized to access the specific resource they requested. It consistently ranks as the most-found issue in real audits, ahead of injection and XSS, because it is easy to miss when an endpoint "obviously" only makes sense for the logged-in user.
Is a security audit a one-time thing or an ongoing process?
It should be ongoing. A one-time audit catches the issues present at that moment, but new code, new dependencies, and new features introduce new risk continuously. Automated scanning in CI plus security-aware code review on every change catches far more over time than a periodic audit alone.
How do we handle a leaked API key or secret?
Rotate it immediately — generate a new key and revoke the old one — rather than just removing it from the latest commit, since it remains readable in git history and may already be compromised. Then find how it leaked (client bundle, public repo, log output) and fix that root cause so it does not recur.