OWASP Top 10 2024 Security Checklist
A developer-focused checklist covering the most critical web application security risks. Use this during code review, security audits, and pre-launch hardening.
The OWASP Top 10 — Quick Reference Table
| # | Category | Risk Level | Key Fix |
|---|---|---|---|
| A01 | Broken Access Control | Critical | Enforce authz server-side on every request |
| A02 | Cryptographic Failures | Critical | Use Argon2id for passwords, AES-GCM for data |
| A03 | Injection (SQL, NoSQL, OS) | Critical | Parameterized queries, input validation |
| A04 | Insecure Design | High | Threat modeling, secure design patterns |
| A05 | Security Misconfiguration | High | Harden defaults, disable unused features |
| A06 | Vulnerable Components | High | SCA tools, automated dependency updates |
| A07 | Auth & Session Failures | High | MFA, secure session management |
| A08 | Software & Data Integrity | Medium | Verify signatures, pin dependencies |
| A09 | Logging & Monitoring Failures | Medium | Centralized logs, alerting on anomalies |
| A10 | SSRF | Medium | Allowlist outbound URLs, block internal ranges |
A03 — Injection Prevention
Injection attacks occur when untrusted data is sent to an interpreter as part of a command or query. SQL injection remains the most exploited vulnerability across all languages and frameworks.
Vulnerable SQL (Never do this)
// ❌ VULNERABLE — direct string interpolation
const query = `SELECT * FROM users WHERE email = '{req.body.email}'`;
// Attacker input: ' OR '1'='1
// Resulting query: SELECT * FROM users WHERE email = '' OR '1'='1'
// Returns ALL users! Safe Parameterized Query (Node.js / pg)
// ✅ SAFE — parameterized query
const result = await pool.query(
'SELECT * FROM users WHERE email = $1',
[req.body.email] // value is never interpolated into SQL
);
// ✅ SAFE — with an ORM (Prisma)
const user = await prisma.user.findFirst({
where: { email: req.body.email }
}); Python SQLAlchemy (Safe)
from sqlalchemy import text
# ✅ SAFE — bound parameters
result = db.execute(
text("SELECT * FROM users WHERE email = :email"),
{"email": email_input}
)
# ❌ VULNERABLE — f-string in query
result = db.execute(f"SELECT * FROM users WHERE email = '{email_input}'") A03 — XSS Prevention
Cross-Site Scripting (XSS) lets attackers inject client-side scripts into pages viewed by other users. Reflected XSS comes from request data; stored XSS persists in the database; DOM-based XSS manipulates client-side code.
Content Security Policy Header
# Nginx — strong CSP header
add_header Content-Security-Policy
"default-src 'self';
script-src 'self' 'nonce-{NONCE}';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.yourapp.com;
frame-ancestors 'none';"
always; Sanitize HTML before rendering (DOMPurify)
import DOMPurify from 'dompurify';
// ❌ XSS risk — never do this with user content
element.innerHTML = userContent;
// ✅ SAFE — sanitize first
const clean = DOMPurify.sanitize(userContent, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href']
});
element.innerHTML = clean; A05 — Security Misconfiguration: CORS
CORS misconfiguration is one of the most common real-world vulnerabilities. A wildcard Access-Control-Allow-Origin: * combined with Access-Control-Allow-Credentials: true is a critical vulnerability that allows any origin to make credentialed requests.
Misconfigured CORS (Dangerous)
// ❌ DANGEROUS — wildcard with credentials
app.use(cors({
origin: '*',
credentials: true // This combination is a critical vuln!
}));
// ❌ DANGEROUS — reflecting Origin header without validation
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Credentials', 'true');
next();
}); Correct CORS Configuration (Express)
// ✅ SAFE — explicit allowlist
const ALLOWED_ORIGINS = [
'https://app.yourcompany.com',
'https://admin.yourcompany.com',
];
app.use(cors({
origin: (origin, callback) => {
if (!origin || ALLOWED_ORIGINS.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
})); A01 — Broken Access Control (IDOR)
Access control enforces that users can only act within their intended permissions. IDOR (Insecure Direct Object Reference) is the most common access control failure found in bug bounty programs.
// ❌ VULNERABLE — no authorization check
app.get('/api/invoices/:id', async (req, res) => {
const invoice = await db.invoices.findById(req.params.id);
res.json(invoice); // Any authenticated user can read any invoice!
});
// ✅ SAFE — verify ownership
app.get('/api/invoices/:id', authenticate, async (req, res) => {
const invoice = await db.invoices.findOne({
id: req.params.id,
userId: req.user.id // Must belong to requesting user
});
if (!invoice) return res.status(404).json({ error: 'Not found' });
res.json(invoice);
}); Security Headers Checklist
| Header | Recommended Value | Protects Against |
|---|---|---|
| Strict-Transport-Security | max-age=63072000; includeSubDomains; preload | SSL stripping, MITM |
| X-Frame-Options | DENY | Clickjacking |
| X-Content-Type-Options | nosniff | MIME sniffing attacks |
| Referrer-Policy | strict-origin-when-cross-origin | Data leakage in Referer |
| Permissions-Policy | camera=(), microphone=(), geolocation=() | Feature abuse |
| Content-Security-Policy | default-src 'self'; ... | XSS, data injection |
Frequently Asked Questions
What is the OWASP Top 10?▼
The OWASP Top 10 is a standard awareness document representing the most critical security risks to web applications. Published by the Open Web Application Security Project, it is updated periodically (most recently for 2021, with 2024 updates) based on data from hundreds of organizations and thousands of applications. It serves as a baseline checklist for secure development practices.
What is the difference between SQL injection and NoSQL injection?▼
SQL injection targets relational databases by inserting malicious SQL syntax into queries. NoSQL injection targets document databases like MongoDB by exploiting JSON/BSON query operators — for example, passing {'$gt': ''} as a password to bypass authentication. Both require parameterized queries or input sanitization. In MongoDB, always use parameterized queries and validate that inputs are the expected type (string, not object).
How do I prevent XSS in a React or Vue application?▼
React and Vue escape output by default when using JSX / template syntax. XSS risks occur when using dangerouslySetInnerHTML (React) or v-html (Vue) — avoid these with untrusted content. Use a library like DOMPurify to sanitize HTML before rendering. For backend-rendered HTML, use context-aware output encoding: HTML-encode for HTML context, JavaScript-encode for JS context, URL-encode for URL params.
What is an IDOR vulnerability and how do I prevent it?▼
Insecure Direct Object Reference (IDOR) occurs when an application exposes internal identifiers (database IDs, filenames) directly and doesn't verify the requesting user is authorized to access that resource. Prevention: always perform authorization checks server-side before returning any object — never rely on the client to enforce access control. Use indirect references (UUIDs instead of sequential integers) and log access attempts.
What is security misconfiguration and what are common examples?▼
Security misconfiguration is the most common OWASP category. Examples include: running services with default credentials, leaving debug mode enabled in production, exposing stack traces in error messages, unnecessary open ports or services, missing security headers (CSP, HSTS, X-Frame-Options), public cloud storage buckets (S3), and overly permissive CORS policies. Remediation involves hardening guides, automated config scanning, and infrastructure-as-code reviews.
What are cryptographic failures and what algorithms should I use in 2024?▼
Cryptographic failures include using broken algorithms (MD5, SHA-1 for passwords, DES), transmitting sensitive data unencrypted, weak key sizes, or misusing cryptographic primitives. For passwords use bcrypt, Argon2id, or scrypt — never SHA-256 alone. For symmetric encryption use AES-256-GCM. For hashing use SHA-256 or SHA-3. For key exchange use ECDH with P-256 or X25519. Always use TLS 1.2+ for data in transit.
Related Products
on GumroadDevPlaybook Interview Vault
210+ real technical interview questions with model answers, asked at Google, Meta, Amazon, Microsoft, Stripe, and Shopify. Covers Frontend (55), Backend (55), System Design (50), and DSA (50). Available in English and Traditional Chinese.
Buy on Gumroad →TypeScript Quick Reference Toolkit
5 practical reference files for TypeScript developers: cheatsheet, TS vs JS comparison, 20 utility types with real examples, tsconfig best practices template, and 15 common mistakes guide. Print it. Keep it on your desk.
Buy on Gumroad →Developer Interview Vault
210 technical interview questions with model answers, key points, and follow-up questions. Covers Frontend, Backend, System Design, and DSA — bilingual English + Traditional Chinese (ZH-TW). PWYW from $29.
Buy on Gumroad →You Might Also Need
Webhook Tester
Generate realistic webhook test payloads for GitHub, Stripe, Slack, and custom services. Get a curl command to send the payload to your local endpoint. Inspect headers, payload size, and content-type.
Open free tool →
WebSocket Tester
Connect to any WebSocket server, send and receive messages in real time, and inspect the message log with timestamps and byte sizes. Free online WebSocket client.
Open free tool →
WebP Converter
Convert PNG, JPG, or GIF images to WebP format in your browser. Drag-and-drop upload, quality slider, before/after file size comparison. No files sent to any server.
Open free tool →
More Free Tools
Related Articles
API Rate Limiting: Algorithms and Implementation Guide 2026
Complete guide to API rate limiting in 2026. Token Bucket, Leaky Bucket, Sliding Window algorithms with Node.js and Redis implementations, distributed rate limiting, 429 handling, and best practices.
Base64 Encoding Explained: When to Use It and When to Avoid It
Base64 encoding explained: when to use it in APIs, image data URIs, and auth tokens. Real-world examples and common pitfalls for web developers.
Node.js Best Practices for Security and Performance in 2026
12 essential Node.js best practices covering security hardening, async patterns, memory management, error handling, and production deployment. With code examples.
API Rate Limiting: Strategies, Algorithms, and Free Tools
A complete guide to API rate limiting in 2025: Fixed Window, Sliding Window, Token Bucket, and Leaky Bucket algorithms explained, with implementation in Node.js, Python, and Go, Redis-based distributed limiting, and client-side backoff strategies.
Environment Variables Best Practices: A Developer's Complete Guide
Master environment variables: how to use them correctly, avoid common security mistakes, manage secrets across environments, and implement .env best practices in any stack.
Enjoying this tool? Get more like it.
Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.
Unlock AI-Powered Dev Tools
- ⚡ AI Code Review, Doc Generator & SQL Builder
- ⚡ All premium templates & early access
- ⚡ Member discounts on Gumroad products
$9/mo after trial · Cancel anytime
Want the full toolkit?
Get DevPlaybook Pro
Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.
MIT licensed · Instant download · No subscription
See what's included → Browse all deals →