Fastify security
Skill hlsitechio/claude-skills-security/appsec-stack-pack/fastify-security
Defensive security audit skills for Claude — tech-stack-keyed and audit-domain-keyed packs for SaaS apps.
npx -y skills add hlsitechio/claude-skills-security --skill fastify-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
- 1 stars1 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
Security audit for Fastify applications including schema validation, hooks (onRequest, preHandler, preValidation), plugin scoping, encapsulation, fastify-helmet/fastify-cors/fastify-rate-limit setup, JSON schema strictness, and Fastify-specific patterns. Use this skill whenever the user mentions Fastify, @fastify/*, fastify-plugin, FastifyInstance, route schemas, fastify hooks, or asks "audit my Fastify app", "Fastify security", "schema validation". Trigger when the codebase contains `fastify` or `@fastify/*` in package.json.
SKILL.md
6.2 KB, as published. Nobody here has run it
Fastify Security Audit
Audit Fastify HTTP servers. Fastify's schema-first design provides strong defaults if used correctly.
When this skill applies
- Reviewing Fastify route definitions and schemas
- Auditing plugin chain and encapsulation
- Reviewing hooks (onRequest, preHandler, preValidation, onResponse)
- Checking security plugin configuration
Workflow
Follow ../_shared/audit-workflow.md. Companion: nodejs-express-security for cross-cutting Node concerns.
Phase 1: Stack detection
grep -E '"fastify":|"@fastify/' package.json
Phase 2: Inventory
# Route definitions
grep -rn 'fastify\.\(get\|post\|put\|delete\|patch\|register\)' src/ | head -50
# Schemas
grep -rnE 'schema:\s*{' src/ | head -20
# Hooks
grep -rn '\.addHook\(\|preHandler:\|preValidation:\|onRequest:' src/
# Security plugins
grep -nE '@fastify/(helmet|cors|rate-limit|jwt|cookie|session|multipart|csrf-protection)' package.json
Phase 3: Detection — the checks
Schema validation
Fastify validates inputs against JSON Schema on every request — if you provide one.
- FST-SCH-1 Every route has a schema for
body,params,querystring. Missing schema = no validation. - FST-SCH-2 Schema uses strict types and ranges:
fastify.post('/users', { schema: { body: { type: 'object', required: ['email', 'password'], additionalProperties: false, // ← strips/rejects extras properties: { email: { type: 'string', format: 'email', maxLength: 254 }, password: { type: 'string', minLength: 8, maxLength: 128 }, }, }, }, }, async (req, reply) => { ... }); - FST-SCH-3
additionalProperties: falseset globally OR on every schema. Without it, mass assignment is possible. - FST-SCH-4 Response schemas defined — they filter the response to only declared fields (built-in defense against accidental data exposure):
schema: { response: { 200: { type: 'object', properties: { id: { type: 'string' }, displayName: { type: 'string' }, // passwordHash explicitly absent }, }, }, } - FST-SCH-5 AJV configured strictly (default in current Fastify); custom keywords reviewed for soundness.
Hooks
Fastify has multiple hook points; auth typically in onRequest or preHandler.
- FST-HK-1 Auth hook applied to protected routes via plugin scope or global hook with opt-out for public routes.
- FST-HK-2 Hooks run in registration order; auth before validation is fine, but verify the order matches intent.
- FST-HK-3 Hooks throwing errors propagate to error handler — don't swallow.
Plugin encapsulation
Fastify plugins create scopes. Auth applied in one plugin doesn't apply to sibling plugins unless registered up-stack:
// BAD — auth only applies to /api/v1 subtree
fastify.register(async (app) => {
app.addHook('preHandler', authHook);
app.register(userRoutes, { prefix: '/api/v1' });
});
// /api/v2 routes registered elsewhere have NO auth
// GOOD — auth at top level
fastify.addHook('preHandler', authHook);
fastify.register(userRoutes, { prefix: '/api/v1' });
fastify.register(adminRoutes, { prefix: '/api/v2' });
- FST-PLG-1 Auth/security hooks at the top level OR encapsulated explicitly per plugin scope.
- FST-PLG-2
fastify-pluginwrapper used when a plugin's effects (including hooks) should escape its scope. Conversely, plugins that should be scoped should NOT usefastify-plugin.
Security plugins
- FST-SP-1
@fastify/helmetregistered. Same options as Express helmet. - FST-SP-2
@fastify/corswith specific origin allowlist. - FST-SP-3
@fastify/rate-limitregistered globally (or per-route for fine-tuning). - FST-SP-4
@fastify/csrf-protectionif using cookie-based session. - FST-SP-5
@fastify/multipartwith size limits if file uploads. - FST-SP-6
@fastify/cookieand@fastify/sessionconfigured securely (httpOnly, secure, sameSite — seesaas-security-pack/saas-frontend-hardening/references/cookie-config.md).
Body parser limits
- FST-BP-1
bodyLimitset on FastifyInstance (default 1MB; lower if appropriate, never higher without specific reason). - FST-BP-2 Per-route override for upload routes only.
JWT (@fastify/jwt)
- FST-JWT-1 Secret/key from env, not committed.
- FST-JWT-2 Algorithm specified (don't accept
none). - FST-JWT-3 See
saas-security-pack/saas-code-security-review/references/jwt-validation.md.
Error handling
- FST-ERR-1
setErrorHandlerconfigured to scrub internal details in production. - FST-ERR-2 Validation errors return generic messages (don't echo full schema paths that reveal internal field names).
Logging
- FST-LOG-1 Fastify's pino logger configured to redact sensitive paths:
const fastify = Fastify({ logger: { redact: ['req.headers.authorization', 'req.headers.cookie', 'req.body.password'], }, }); - FST-LOG-2 No password / token in request bodies logged at info level.
Microservice / WS
If using @fastify/websocket:
- FST-WS-1 WebSocket connection auth via the initial HTTP upgrade — same auth as REST routes.
- FST-WS-2 Origin validation on upgrade.
Dependencies
- FST-DEP-1 Fastify v4 or v5 (current). Older versions deprecated.
- FST-DEP-2
@fastify/*packages match Fastify major version.
Phase 4: Triage
Critical: route without schema accepting body; encapsulation bug where auth hook missing from a route group; default bodyLimit with file upload routes.
Phase 5: Report
Use ../_shared/findings-schema.md. Prefix IDs with FST-.