Security Fundamentals

OWASP Top 10 Explained

Walk through every OWASP Top 10 vulnerability with real examples and concrete prevention techniques.

What Is OWASP?

The Open Web Application Security Project (OWASP) is a nonprofit foundation that works to improve software security. Their Top 10 list — published every few years — represents the most critical security risks to web applications, ranked by frequency, exploitability, and business impact.

Understanding the OWASP Top 10 is not optional for any developer who ships production software.

1. Broken Access Control

What it is: Users can access resources or perform actions they are not authorized for.

Example: A URL like /api/users/123 returns user data. User with ID 456 changes the URL to /api/users/123 and sees another user's private information.

Prevention: Validate authorization on every server-side request. Never rely on the client to enforce access control.

typescript
// Vulnerable
export async function GET(req: Request, { params }) {
  return db.users.findById(params.id); // No authorization check!
}

// Secure
export async function GET(req: Request, { params }) {
  const currentUser = await getAuthUser(req);
  if (currentUser.id !== params.id && currentUser.role !== 'admin') {
    return Response.json({ error: 'Forbidden' }, { status: 403 });
  }
  return db.users.findById(params.id);
}

2. Cryptographic Failures

What it is: Sensitive data exposed due to weak or missing encryption.

Prevention: Encrypt sensitive data at rest and in transit. Use strong, modern algorithms. Never implement your own cryptography.

3. Injection

What it is: Untrusted data sent to an interpreter as part of a command or query.

SQL Injection Example:

typescript
// Vulnerable — user input directly in query string
const result = await db.query(
  `SELECT * FROM users WHERE email = '${email}'`
);
// Attacker inputs: ' OR '1'='1
// Query becomes: SELECT * FROM users WHERE email = '' OR '1'='1'
// Returns all users!

// Secure — parameterized query
const result = await db.query(
  'SELECT * FROM users WHERE email = $1',
  [email]
);

4. Insecure Design

What it is: Flawed security architecture decisions made early in development that cannot be patched away.

Prevention: Threat modeling during design phase. Ask "how could this be abused?" before building each feature.

5. Security Misconfiguration

What it is: Default credentials, verbose error messages, unnecessary services, misconfigured permissions.

Common examples:

  • Default admin password unchanged
  • Stack traces visible to end users in production
  • AWS S3 bucket publicly readable
  • Directory listing enabled on web server

Prevention: Harden defaults, review configurations in every environment, use automated scanning.

6. Vulnerable and Outdated Components

What it is: Using libraries with known security vulnerabilities.

Prevention:

bash
# Scan for known vulnerabilities
npm audit

# Fix automatically where possible
npm audit fix

# Use Dependabot or Snyk for continuous monitoring

7. Identification and Authentication Failures

What it is: Weak authentication allows attackers to compromise accounts.

Prevention: MFA, account lockout after failed attempts, strong password requirements, rate limiting on auth endpoints.

8. Software and Data Integrity Failures

What it is: Code or data from untrusted sources without integrity verification.

Prevention: Verify package integrity (npm uses lockfiles and checksums), sign your deployments, protect your CI/CD pipeline.

9. Security Logging and Monitoring Failures

What it is: No audit trail means you cannot detect attacks or investigate incidents after the fact.

Prevention: Log authentication events, access control failures, and input validation failures. Set up alerts for anomalous patterns.

10. Server-Side Request Forgery (SSRF)

What it is: An attacker tricks your server into making requests to internal resources.

Example: A feature that fetches a URL provided by the user. Attacker provides http://169.254.169.254/latest/meta-data/ (AWS instance metadata endpoint) and retrieves cloud credentials.

Prevention: Validate and allowlist URLs your server will fetch. Use network-level controls to prevent access to internal IP ranges.

Key Takeaways

  • Access control must be enforced server-side on every request — never trust the client
  • SQL injection prevention: always use parameterized queries or ORMs, never concatenate user input into queries
  • Keep dependencies updated and scan regularly with npm audit or Snyk
  • Log security-relevant events (logins, access denials, input errors) to detect and investigate attacks
  • Design for security from the start — you cannot patch away a fundamentally insecure architecture

Example

typescript
// Preventing the three most critical OWASP vulnerabilities

// 1. Broken Access Control — server-side authorization
export async function DELETE(req: Request, { params }) {
  const user = await getAuthUser(req);
  const resource = await db.resources.findById(params.id);

  if (!resource) return Response.json({ error: 'Not found' }, { status: 404 });
  if (resource.userId !== user.id) return Response.json({ error: 'Forbidden' }, { status: 403 });

  await db.resources.delete(params.id);
  return Response.json({ success: true });
}

// 3. SQL Injection — parameterized queries
const user = await db.query(
  'SELECT * FROM users WHERE email = $1 AND active = $2',
  [email, true]
);

// 7. Auth Failures — rate limiting
const attempts = await redis.incr(`login:attempts:${ip}`);
if (attempts > 5) {
  return Response.json({ error: 'Too many attempts' }, { status: 429 });
}
Try it yourself — TYPESCRIPT

Docker, AWS, Vercel, Netlify, GitHub, GitHub Actions are trademarks of Docker, Inc., Amazon.com, Inc., Vercel, Inc., Netlify, Inc., Microsoft Corporation. DevForge Academy is not affiliated with, endorsed by, or sponsored by these companies. Referenced for educational purposes only. See full disclaimers