Troja
All posts
OWASPMar 5, 2026·18 min read

OWASP Top 10 for Indie Hackers: A No-Nonsense Guide

The OWASP Top 10 without the enterprise jargon. Each category explained for a solo dev shipping a SaaS — what it is, how it bites you, and the one fix that matters.

By Security Desk

The Top 10, for a team of one

The OWASP Top 10 is the industry's consensus list of the most critical web app security risks. It's written for enterprises; you're one person shipping a SaaS. Here's each category translated into what actually matters for you — what it is, how it bites, and the highest-leverage fix.

A01: Broken Access Control

The #1 risk, and the one you'll most likely have. A logged-in user accesses data or actions they shouldn't — usually by changing an ID (IDOR).

// Always scope to the owner
const doc = await getDoc(id);
if (doc.ownerId !== session.user.id) return forbidden();

Fix: ownership check on every record access; enforce it server-side (and in RLS if you use Supabase/Firebase). Never trust a client-supplied ID alone.

A02: Cryptographic Failures

Sensitive data exposed because it wasn't protected — secrets in the client bundle, passwords hashed with MD5, traffic over HTTP, PII in plaintext.

Fix: HTTPS everywhere; hash passwords with bcrypt/argon2; keep secrets in env vars; don't log tokens. Use a real auth provider rather than rolling crypto yourself.

A03: Injection

Untrusted input interpreted as code or query — SQL injection, command injection, XSS.

// Parameterize, never interpolate
await db.query("SELECT * FROM users WHERE id = $1", [id]);

Fix: parameterized queries, ORM query builders, output encoding, and a strict CSP for XSS. Validate input on top.

A04: Insecure Design

The flaw is in the plan, not the code — e.g., a password reset with no rate limit, or trusting the client to send the price. You can't patch your way out of a bad design.

Fix: think about abuse cases up front. "What if they call this 10,000 times? What if they change this field?" Design the limit in, not on.

A05: Security Misconfiguration

Default credentials, verbose errors, open cloud buckets, missing headers, test-mode database rules. Extremely common in fast-shipped apps.

X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'
X-Frame-Options: DENY

Fix: set security headers, disable debug/verbose errors in production, lock down BaaS rules, and change every default.

A06: Vulnerable and Outdated Components

A dependency with a known CVE is how a lot of "advanced" breaches actually start.

npm audit --omit=dev

Fix: run audits in CI, patch high/critical promptly, and remove dependencies you don't use.

A07: Identification and Authentication Failures

Weak passwords allowed, no brute-force protection, predictable sessions, broken password reset, user-enumeration oracles.

Fix: use a vetted auth library; rate-limit auth endpoints; return generic "invalid email or password"; expire and rotate sessions; offer MFA.

A08: Software and Data Integrity Failures

Trusting code or data you didn't verify — an unsigned auto-update, an unverified webhook, a compromised CI dependency.

// Verify webhook signatures — never trust the payload alone
const event = stripe.webhooks.constructEvent(rawBody, sig, secret);

Fix: verify signatures on webhooks and updates; pin/lock dependencies; protect your CI/CD secrets.

A09: Security Logging and Monitoring Failures

You can't respond to an attack you can't see. Most indie apps log nothing security-relevant, so a breach is discovered weeks later — by someone else.

Fix: log auth events, admin actions, and access-control failures. Send alerts on anomalies. You don't need a SIEM; you need visibility.

A10: Server-Side Request Forgery (SSRF)

Your server fetches a URL the user controls, and the attacker points it at internal services or cloud metadata endpoints.

// Allowlist outbound destinations; block internal ranges
if (!isAllowedHost(new URL(userUrl).hostname)) throw new Error("Blocked");

Fix: allowlist hosts for any user-supplied URL fetch, and block requests to private/link-local IP ranges and 169.254.169.254.

Your realistic priority order

As a solo dev, you'll most likely have, in order:

  1. A01 Broken Access Control (IDOR) — check this first.
  2. A05 Misconfiguration — headers, BaaS rules, debug mode.
  3. A02 Crypto failures — exposed secrets.
  4. A03 Injection — string-built SQL, XSS.
  5. A07 Auth failures — rate limits, enumeration.

Fix those five and you've eliminated the overwhelming majority of real-world risk for an app your size.

Scan it with Troja

Troja maps its findings to the OWASP Top 10 so you can see exactly where you stand on each category — and ships a fix prompt with every issue. Run a scan and turn this list into a clean checklist.

Run the scan this post is about.

Free, no signup. See what's hiding inside your walls in ~30 seconds.

Free scan · no signup · results in ~30 seconds
OWASP Top 10 for Indie Hackers: A No-Nonsense Guide — Troja