APIs handle authentication tokens, payment data, and personal information. They're also the most exposed surface of your application, public by design, documented for convenience, and often the last thing that gets security tested.
In 2026, APIs are the #1 attack vector for web applications. This guide covers the OWASP API Security Top 10, practical testing techniques, and tools you can use today.
OWASP API Security Top 10 (2023 Edition)
| # | Vulnerability | What it means | How to test |
|---|---|---|---|
| 1 | BOLA (Broken Object Level Auth) | User A can access User B's data by changing the ID | Change resource IDs in requests with a different user's token |
| 2 | Broken Authentication | Weak auth mechanisms, missing token validation | Send requests without tokens, with expired tokens, with manipulated JWTs |
| 3 | Broken Object Property Auth | User can modify fields they shouldn't (mass assignment) | Send extra fields in POST/PUT (role, isAdmin, price) |
| 4 | Unrestricted Resource Consumption | No rate limiting, allows DoS | Send 1000 requests/second, check if throttled |
| 5 | Broken Function Level Auth | Regular user can access admin endpoints | Try admin routes with regular user tokens |
| 6 | Unrestricted Access to Sensitive Flows | No protection on critical flows (checkout, password reset) | Automate critical flows without CAPTCHA/limits |
| 7 | Server-Side Request Forgery | API fetches attacker-controlled URLs | Pass internal URLs (localhost, metadata endpoints) in URL params |
| 8 | Security Misconfiguration | Verbose errors, default credentials, CORS misconfigured | Check error responses, CORS headers, default passwords |
| 9 | Improper Inventory Management | Old API versions still exposed, undocumented endpoints | Scan for /v1/, /api-old/, /internal/ paths |
| 10 | Unsafe Consumption of APIs | Your API trusts third-party APIs blindly | Test with malicious responses from mocked third-party APIs |
Practical Security Tests
Test 1: BOLA (the most common vulnerability)
// Test: Can user A access user B's order?
// Login as User A, get their token
const tokenA = await login('usera@test.com', 'password')
// Try to access User B's order with User A's token
const res = await fetch('/api/orders/user-b-order-id', {
headers: { Authorization: `Bearer ${tokenA}` },
})
// PASS: should return 403 Forbidden
// FAIL: returns 200 with User B's order data
expect(res.status).toBe(403)Test 2: Mass Assignment
// Test: Can a user set themselves as admin?
const res = await fetch('/api/users/me', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${userToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Legit Update',
role: 'admin', // Should be ignored
isVerified: true, // Should be ignored
}),
})
const user = await res.json()
// PASS: role and isVerified unchanged
// FAIL: user is now admin
expect(user.role).toBe('user')
expect(user.isVerified).toBe(false)Test 3: Rate Limiting
// Test: Does the API throttle excessive requests?
const results = []
for (let i = 0; i < 100; i++) {
const res = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ email: 'test@test.com', password: 'wrong' }),
})
results.push(res.status)
}
// PASS: some requests return 429 (Too Many Requests)
// FAIL: all 100 return 401 (no rate limiting)
expect(results.filter(s => s === 429).length).toBeGreaterThan(0)API Security Testing Tools
| Tool | Type | Price | Best for |
|---|---|---|---|
| OWASP ZAP | DAST scanner | Free (open source) | Automated scanning in CI/CD |
| Burp Suite | Proxy + scanner | Free (Community) / $449/yr (Pro) | Manual penetration testing |
| Postman | API client | Free / $14/user/mo | Manual test collections |
| 42Crunch | API-specific audit | Free tier / custom | OpenAPI spec security audit |
| StackHawk | CI/CD DAST | Free tier / $35/mo | Automated security in pipelines |
Security Testing vs Security Monitoring
Security testing runs before deployment. But attackers don't wait for your test schedule. You need runtime monitoring to detect anomalies in production:
- Spike in 401/403 errors → possible brute force or credential stuffing attack
- Spike in 400 errors → possible injection attempt or fuzzing
- Unusual traffic patterns → possible enumeration or scraping
Track error rates per endpoint and alert on sudden changes: if /api/login suddenly gets 500 401s in 60 seconds, you want to know within minutes, not in a security report next quarter. Your existing observability stack (logs plus an alert rule on 401/403 counts per route) is usually enough to start.
Testing and monitoring still depend on you knowing where the holes are. Nurbak's AI pentester scans your repo for missing auth checks, broken access control, injection and other exploitable bugs, and can open a PR with the fix. Your first scan is free.
