jrdnhnz.dev
← Back to Blog

May 12, 2026 · 9 min read

OWASP Top 10 for Full Stack Developers: What I Actually See in the Wild

The OWASP risks that show up in real SaaS builds — injection, broken auth, IDOR, misconfig — and how I harden against them.

securityowaspfullstackresearch

OWASP Top 10 reads like a list. In real SaaS builds it reads like a pattern book — the same few issues show up across OTP platforms, marketplaces, and streaming apps, in slightly different costumes. This is what I actually see in the wild, framed as research.

Injection — still the cheapest win

It's not 2010 SQL-string-concatenation anymore; it's second-order injection and trusting client shape. The fix is the same idea: never interpolate, always parameterize and schema-parse.

  • SQL: parameterized queries / the ORM's bind. Never string-build.
  • Inputs: zod-parse at the boundary. If it isn't the shape you expect, reject before it touches a query, a shell, or a template.
const Body = z.object({
  email: z.string().email(),
  amount: z.number().int().positive(),
});
// parse → reject → then use the typed value
const { email, amount } = Body.parse(req.body);

Broken Access Control (IDOR)

This is the one I see most. A user fetches /api/orders/123 and it works — because the handler checks "is logged in" but not "does order 123 belong to you". That's an IDOR. Object-level authorization on every fetch/mutate, not just route-level auth.

const order = await getOrder(id);
if (order.userId !== session.userId) return notFound(); // not 403 — don't leak existence

Return 404, not 403, so you don't confirm the object exists.

Identification & Auth failures

JWT discipline:

  • Short access-token TTL (minutes), refresh-token rotation, server-side verification only.
  • Invalidate refresh tokens on reuse (rotation detection).
  • Don't put secrets in the JWT payload — it's base64, not encrypted.

The mistake I see most: long-lived access tokens stored in localStorage, with no rotation. Treat access tokens like perishables.

Security Misconfiguration

  • Verbose errors off in production — stack traces are a map for attackers.
  • Secrets in env, never in the bundle or the repo. process.env.SECRET, not a hardcoded string.
  • CORS: explicit origins, not * when credentials are involved.
  • Headers: Strict-Transport-Security, X-Content-Type-Options: nosniff, a reasonable CSP.

Vulnerable & Outdated Components

Lockfiles are a dependency manifest and an attack surface. Keep them pinned, enable Dependabot/Renovate, and review transitive deps. The supply-chain lesson from the last few years is that your node_modules is part of your perimeter.

The throughline

Every item above is the same idea in different clothes: don't trust input, don't trust the client, don't trust the caller's claim about identity. Verify at the boundary, authorize at the object, and treat the framework as a tool that still needs you to think. The Top 10 isn't a checklist to memorize — it's a habit to build: assume the input is hostile, then write the handler anyway.