Install
openclaw skills install @heroinyan-stack/api-security-auditorPerforms a detailed API security audit of REST and GraphQL endpoints against OWASP API Top 10 (2023), identifying auth flaws, injections, rate limits, data e...
openclaw skills install @heroinyan-stack/api-security-auditorComprehensive API security audit based on OWASP API Security Top 10 (2023). Scans REST and GraphQL APIs for authentication flaws, authorization bypass, injection, excessive data exposure, rate limiting gaps, and misconfigured CORS — outputs a prioritized fix list with code examples.
APIs are the #1 attack vector for web applications (Gartner, 2026). Traditional web security scanners miss API-specific vulnerabilities like BOLA (Broken Object Level Authorization), mass assignment, and excessive data exposure. This skill is purpose-built for API security.
Activate when the user:
Catalog all API endpoints:
| Method | Path | Auth Required | Description |
|---|---|---|---|
| GET | /api/v1/users | ✅ | List users |
| GET | /api/v1/users/:id | ✅ | Get user by ID |
| POST | /api/v1/users | ❌ | Create user (signup) |
| PATCH | /api/v1/users/:id | ✅ | Update user |
| DELETE | /api/v1/users/:id | ✅ (admin) | Delete user |
| POST | /api/v1/auth/login | ❌ | Login |
| POST | /api/v1/auth/refresh | ✅ | Refresh token |
| GET | /api/v1/users/:id/orders | ✅ | Get user's orders |
Also check:
The #1 API vulnerability. Test every endpoint that takes an object ID:
// VULNERABLE: User can access other users' data
app.get('/api/users/:id', auth, (req, res) => {
const user = db.getUser(req.params.id); // No ownership check!
res.json(user);
});
// SECURE: Verify ownership
app.get('/api/users/:id', auth, (req, res) => {
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' });
}
const user = db.getUser(req.params.id);
res.json(user);
});
Check every endpoint:
| Check | Issue | Fix |
|---|---|---|
| Password reset token reusable | Token doesn't expire after use | One-time use + 15min expiry |
| JWT alg=none accepted | Server accepts unsigned tokens | Whitelist specific algorithms |
| No rate limit on login | Brute force possible | 5 attempts / 15 min / IP |
| Refresh token never expires | Token theft = permanent access | 7-day rotation + reuse detection |
| API key in URL | Logged in server logs/nginx | Move to Authorization: Bearer header |
| No email verification | Account takeover via signup | Verify before granting access |
Mass Assignment:
// VULNERABLE: User can set isAdmin
app.patch('/api/users/:id', auth, (req, res) => {
db.updateUser(req.params.id, req.body); // Accepts ALL fields!
});
// SECURE: Whitelist allowed fields
app.patch('/api/users/:id', auth, (req, res) => {
const allowedFields = ['name', 'email', 'avatar'];
const updates = pick(req.body, allowedFields);
db.updateUser(req.params.id, updates);
});
Excessive Data Exposure:
// VULNERABLE: Returns password hash, internal IDs, admin flags
app.get('/api/users/:id', auth, (req, res) => {
const user = db.getUser(req.params.id);
res.json(user); // Everything!
});
// SECURE: Explicit field selection
app.get('/api/users/:id', auth, (req, res) => {
const user = db.getUser(req.params.id, {
select: ['id', 'name', 'email', 'avatar', 'createdAt']
});
res.json(user);
});
| Check | Limit | Recommendation |
|---|---|---|
| Rate limiting | None | 100 req/min/user, 1000 req/min/IP |
| File upload size | Unlimited | 10MB max, validate MIME type |
| Pagination | None | Max 100 items per page |
| Query complexity (GraphQL) | Unlimited | Depth limit 10, complexity scoring |
| Compression bomb | Not checked | Max decompressed size check |
| Memory usage | Not tracked | Per-request memory limit |
// VULNERABLE: Admin endpoint check only on frontend
app.delete('/api/users/:id', auth, (req, res) => {
db.deleteUser(req.params.id); // No role check!
});
// SECURE: Verify role on backend
app.delete('/api/users/:id', auth, requireRole('admin'), (req, res) => {
db.deleteUser(req.params.id);
});
Access-Control-Allow-Origin: * with credentials/api/v1/ alongside /api/v2/)## Rate Limiting Audit
| Endpoint | Current Limit | Recommended | Method |
|----------|--------------|-------------|--------|
| POST /auth/login | None | 5/15min/IP | Fixed window |
| POST /auth/signup | None | 3/hour/IP | Fixed window |
| GET /api/* | None | 100/min/user | Sliding window |
| POST /api/upload | None | 10/min/user | Token bucket |
| GraphQL /api/graphql | None | 30/min/user + depth limit | Complexity-based |
## Missing Protections
- ❌ No global rate limit middleware
- ❌ No per-user rate limit (only IP-based)
- ❌ No GraphQL query depth/complexity limiting
- ❌ No DDoS protection (Cloudflare/AWS Shield)
- ❌ No CAPTCHA on auth endpoints after failed attempts
# 🔐 API Security Audit Report
## Executive Summary
| Severity | Count | Categories |
|----------|-------|------------|
| 🔴 Critical | 3 | BOLA, Broken Auth, Mass Assignment |
| 🟠 High | 5 | Rate Limiting, Excessive Data, CORS |
| 🟡 Medium | 4 | Error Handling, Headers, API Versioning |
| 🔵 Low | 2 | Documentation, Monitoring |
**Overall Risk: CRITICAL — Immediate action required**
## Prioritized Fix List
### 🔴 Fix Immediately (Today)
1. **BOLA on GET /api/users/:id** — Any user can read any other user's data
2. **Mass Assignment on PATCH /api/users/:id** — Users can set `isAdmin: true`
3. **No rate limit on POST /auth/login** — Brute force attack possible
### 🟠 Fix This Week
4. Add rate limiting middleware (express-rate-limit / slowapi)
5. Implement field selection on all user endpoints
6. Fix CORS: remove wildcard origin, use allowlist
7. Add GraphQL depth/complexity limiting
8. Disable old API version (v1)
[... full report with code examples for each fix ...]