docs/templates/skills/api-security-guard/SKILL.md
Auto-trigger when detecting modifications to API endpoints, request handlers, authentication middleware, or input validation code. Validates API security best practices without blocking user flow.
npx skillsauth add reefbytes-owner/manifest api-security-guardInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill automatically activates when Claude detects changes to API-related code.
Activate when code modifications touch any of these patterns:
Express.js (Node.js):
app.get(, app.post(, app.put(, app.delete(, app.patch(router.get(, router.post(, etc.express.Router()req.params, req.query, req.bodyDjango (Python):
@api_viewclass.*APIView, class.*ViewSetrequest.GET, request.POST, request.dataserializers., SerializerFastAPI (Python):
@app.get(, @app.post(, etc.@router.get(, @router.post(, etc.Request, Response, HTTPExceptionFlask (Python):
@app.route(@blueprint.route(request.args, request.form, request.jsonGo (net/http, Gin, Echo):
http.HandleFuncrouter.GET(, router.POST(, etc.c.Param(, c.Query(, c.Bind(ServeHTTPRails (Ruby):
def create, def update, def destroyparams.require(, params.permit(When triggered, this skill performs lightweight, non-blocking validation:
This skill does NOT invoke parallel agents (must remain lightweight for auto-trigger).
Verify that user input is validated before use:
Good patterns:
# Python/FastAPI
from pydantic import BaseModel, validator
class CreateUserRequest(BaseModel):
email: str
age: int
@validator('email')
def validate_email(cls, v):
if '@' not in v:
raise ValueError('Invalid email')
return v
// JavaScript/Express with Joi
const Joi = require('joi');
const schema = Joi.object({
email: Joi.string().email().required(),
age: Joi.number().integer().min(0).max(120).required()
});
const { error, value } = schema.validate(req.body);
Bad patterns:
# NO validation!
email = request.json['email']
user = User.objects.filter(email=email) # SQL injection risk
Check:
Verify that protected endpoints require authentication:
Good patterns:
# Python/Django
from rest_framework.permissions import IsAuthenticated
class UserViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
// JavaScript/Express
const requireAuth = require('./middleware/auth');
app.post('/api/users', requireAuth, createUserHandler);
Bad patterns:
// NO authentication!
app.post('/api/users/:id/delete', async (req, res) => {
await User.deleteOne({ _id: req.params.id });
// Anyone can delete any user!
});
Check:
Verify that users can only access their own resources:
Good patterns:
# Python - Check ownership
def get_user_profile(request, user_id):
if request.user.id != user_id and not request.user.is_admin:
raise PermissionDenied("Cannot access other users' profiles")
return User.objects.get(id=user_id)
// JavaScript - Filter by authenticated user
app.get('/api/orders', requireAuth, async (req, res) => {
const orders = await Order.find({ userId: req.user.id });
// Only return orders belonging to authenticated user
});
Bad patterns:
// IDOR vulnerability!
app.get('/api/orders/:id', requireAuth, async (req, res) => {
const order = await Order.findById(req.params.id);
// No ownership check! Any authenticated user can see any order
});
Check:
Verify that high-risk endpoints have rate limits:
High-risk endpoints:
/auth/login)/auth/reset-password)/contact, /invite)POST /api/users, POST /api/orders)Good patterns:
// Express with express-rate-limit
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 requests per window
message: 'Too many login attempts, please try again later'
});
app.post('/auth/login', loginLimiter, loginHandler);
# Django with django-ratelimit
from django_ratelimit.decorators import ratelimit
@ratelimit(key='ip', rate='5/15m', method='POST')
def login(request):
# ...
Check:
Verify that state-changing endpoints are CSRF-protected:
Applies to:
Good patterns:
# Django (CSRF enabled by default)
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def transfer_money(request):
# ...
// Express with csurf
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.post('/transfer', csrfProtection, transferHandler);
Check:
Verify that database queries use parameterized queries:
Good patterns:
# Python - Parameterized query
user = User.objects.filter(email=email).first() # Django ORM - safe
# Or with raw SQL
cursor.execute("SELECT * FROM users WHERE email = %s", [email]) # Safe
// JavaScript - Parameterized query
const user = await User.findOne({ email: email }); // Mongoose - safe
// Or with raw SQL
db.query('SELECT * FROM users WHERE email = ?', [email]); // Safe
Bad patterns:
# String concatenation - VULNERABLE!
query = f"SELECT * FROM users WHERE email = '{email}'"
cursor.execute(query)
Check:
When this skill detects issues, it provides inline feedback:
🛡️ API Security Guard Findings:
✅ Input validation: PASS
- Request schema defined (CreateUserRequest)
- Email format validated
- Age bounds checked (0-120)
⚠️ Authorization: WARNING
- User ID taken from request body instead of auth context
- Recommendation: Use req.user.id from authentication middleware
❌ Rate limiting: FAIL
- POST /api/users/create has no rate limit
- High risk: Resource creation endpoint
- Add rate limiter: 100 requests per 15 minutes
✅ CSRF protection: PASS
- csrfProtection middleware applied
✅ SQL injection: PASS
- Using Sequelize ORM (safe)
To disable specific checks, add to .claude/config/skill_config.yml:
skills:
api-security-guard:
enabled: true
checks:
input_validation: true
authentication: true
authorization: true
rate_limiting: true
csrf_protection: true
sql_injection: true
templates/skills/database-migration-guard - Schema change validationtemplates/skills/secret-detection-guard - Credential leak preventiontemplates/validation-overrides/web-framework-security.yml - Framework-specific rulestesting
Auto-trigger when detecting database migration files or schema changes. Validates migration safety and backwards compatibility without blocking user flow.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.