APIs are the arteries of modern applications—they move data between microservices, mobile clients, third-party integrations, and partner networks. But they're also attack surfaces. In 2026, API security breaches are the leading cause of data loss in SaaS platforms. This guide covers the threats that matter most and defenses that actually work.
1. Injection Attacks: The persistent nightmare
SQL injection, NoSQL injection, and command injection remain the most exploited API vulnerabilities. The pattern is always the same: untrusted user input flows into a backend query without sanitization.
SQL Injection via API
The attack: An attacker crafts a query parameter to close a SQL statement early and inject malicious SQL:
// Vulnerable endpoint GET /api/users?id=1 OR 1=1
// Backend code (Node.js) const query = `SELECT * FROM users WHERE id = ${req.query.id}`; db.query(query); // Executes: SELECT * FROM users WHERE id = 1 OR 1=1 // Returns ALL users, not just id=1
The fix: Use parameterized queries (prepared statements):
// Secure const query = 'SELECT * FROM users WHERE id = ?'; db.query(query, [req.query.id]); // Driver handles escaping
// ORMs are safer User.findById(req.query.id); // Parameterized by default
NoSQL Injection
Even NoSQL databases aren't immune. Attackers can inject query operators:
APIs often implement weak authentication—hardcoded API keys, expired tokens accepted, or missing role checks.
Common vulnerabilities:
Hardcoded API keys: Secrets embedded in code or published in public GitHub repositories.
Expired tokens accepted: API continues to honor JWT tokens after expiration.
Missing role checks: Admin-only endpoints don't verify user role before execution.
Credential stuffing: Attackers use leaked username/password pairs to brute-force login endpoints.
CORS misconfiguration: API allows requests from untrusted origins, enabling cross-origin token theft.
Hardened authentication pattern:
// 1. Store API keys as bcrypt hashes (never in plaintext) const keyHash = bcrypt.hashSync(apiKey, 10); db.apiKeys.insert({ userId, hash: keyHash, createdAt: now });
// 3. Enforce roles on protected endpoints router.delete('/users/:id', requireRole('admin'), (req, res) => { // Only admins can reach this });
3. Insufficient Rate Limiting & API Abuse
Without rate limits, attackers can scrape your entire database, enumerate users, or launch credential stuffing attacks at scale.
Attack scenarios:
Scraping
Attacker iterates through sequential IDs: GET /api/users/1, /api/users/2, /api/users/3... without rate limits, they download all user records in minutes.
Credential Stuffing
Attacker sends login requests with leaked passwords: POST /api/login with 1M attempts/day. Even a 1% success rate compromises 10,000 accounts.
Effective rate limiting strategy:
// Use Redis for distributed rate limiting const rateLimit = require('express-rate-limit');
A user accesses another user's data by changing an ID in the URL: GET /api/users/999 (where they own /api/users/123). If the API doesn't verify ownership, they see another user's private data.
// Vulnerable router.get('/users/:id', (req, res) => { const user = User.findById(req.params.id); res.json(user); // No ownership check });
✓ All inputs validated against schema (zod, joi, yup)
✓ All database queries use parameterized statements
✓ Authentication enforced on all protected endpoints
✓ Tokens have short expiration times (15min access, 7day refresh)
✓ Rate limiting active per-user and per-IP
✓ Pagination enforced (max 100 records per request)
✓ Authorization checks on resource access (BOLA protection)
✓ Sensitive fields excluded from response serialization
✓ Error messages don't leak internal system details
✓ All API access logged with timestamps and user IDs
✓ CORS headers restricted to trusted origins
✓ HTTPS enforced; HTTP redirects to HTTPS
Securing APIs is a continuous process. The threats evolve as attackers discover new patterns. This is the foundation I build for teams developing SaaS platforms and microservices architectures.
Common questions
What is API injection and why is it dangerous?
API injection occurs when untrusted user input flows into API commands (SQL, NoSQL, OS commands) without sanitization. An attacker manipulates the input to execute unintended logic—reading sensitive data, modifying records, or executing arbitrary code. Always use parameterized queries and input validation.
How do I protect against credential stuffing?
Implement rate limiting on login endpoints (10 attempts per minute per IP). Require multi-factor authentication (MFA) for accounts. Monitor login failure patterns and alert on suspicious activity. Use CAPTCHA on repeated failures to block automated attacks.
Should I version my API?
Yes. Use URL versioning (/api/v1/, /api/v2/) or header-based versioning. This lets you deprecate old endpoints safely without breaking existing clients. Maintain backward compatibility for at least 2 versions.
What's the difference between authentication and authorization?
Authentication verifies who you are (login). Authorization checks what you're allowed to do (roles/permissions). Both are essential: authenticate first, then authorize every action.
Building secure APIs?
I help teams audit API security, implement authentication systems, and scale infrastructure with proper access controls.