Api security
Security skills for AI coding agents. Install once, write secure code every time.
npx -y skills add hereshecodes/secureskills --skill api-securityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when building REST APIs, GraphQL endpoints, or webhooks
SKILL.md
3.0 KB, as published. Nobody here has run it
API Security
Every API endpoint needs authentication, rate limiting, input validation, and proper CORS configuration.
Related: authentication, input-validation, access-control, security-context
Rule 1: Authenticate Every Endpoint
Default to requiring auth. Explicitly mark public endpoints.
// WRONG — endpoint is open to anyone
app.get('/api/users', async (req, res) => {
res.json(await getUsers());
});
// RIGHT — require authentication
app.get('/api/users', requireAuth, async (req, res) => {
res.json(await getUsers());
});
Rule 2: Rate Limit All Endpoints
Prevent abuse and brute force attacks. Apply stricter limits to auth endpoints.
// WRONG — no rate limiting
app.post('/api/login', loginHandler);
// RIGHT — rate limited (stricter on auth routes)
app.post('/api/login', rateLimit({ windowMs: 15 * 60 * 1000, max: 5 }), loginHandler);
app.use('/api/', rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));
Rule 3: Configure CORS Restrictively
Never allow all origins in production.
// WRONG — allows any website to call your API
app.use(cors({ origin: '*' }));
// RIGHT — whitelist specific origins
app.use(cors({
origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true
}));
Rule 4: Limit Request Size
Prevent denial-of-service via large payloads.
// WRONG — no size limit (default can be very large)
app.use(express.json());
// RIGHT — explicit size limit
app.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ limit: '1mb', extended: true }));
Rule 5: Don't Leak Error Details in Production
Internal errors reveal architecture to attackers.
// WRONG — sends stack trace to client
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message, stack: err.stack });
});
// RIGHT — generic message to client, full details to logs
app.use((err, req, res, next) => {
logger.error(err);
res.status(500).json({ error: 'Internal server error' });
});
Rule 6: Validate Content-Type
Reject requests with unexpected content types.
// WRONG — accepts anything
app.post('/api/data', handler);
// RIGHT — enforce expected content type
app.post('/api/data', (req, res, next) => {
if (!req.is('application/json')) {
return res.status(415).json({ error: 'Content-Type must be application/json' });
}
next();
}, handler);
Quick Reference
| Do | Don't |
|---|---|
| Require auth on all endpoints by default | Leave endpoints open accidentally |
| Rate limit (stricter on auth routes) | Allow unlimited requests |
| Whitelist CORS origins | Use origin: '*' in production |
| Limit request body size | Accept unlimited payload sizes |
| Return generic errors to clients | Send stack traces to clients |
| Validate Content-Type headers | Accept any content type |