middleware-patterns — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited middleware-patterns (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Patterns for building robust Express.js middleware chains.
Middleware executes in the order it is registered. Order matters: authentication must run before authorization, and error handlers must be last.
import express from 'express'
const app = express()
// 1. Built-in middleware
app.use(express.json({ limit: '10kb' }))
app.use(express.urlencoded({ extended: true }))
// 2. Security / CORS
app.use(corsMiddleware)
// 3. Rate limiting
app.use(rateLimiter)
// 4. Request logging
app.use(requestLogger)
// 5. Routes (with route-specific middleware)
app.use('/api/v1/auth', authRoutes)
app.use('/api/v1/users', authenticate, userRoutes)
app.use('/api/v1/admin', authenticate, authorize('admin'), adminRoutes)
// 6. 404 handler
app.use(notFoundHandler)
// 7. Error handler (must be last, must have 4 parameters)
app.use(errorHandler)Verify tokens and attach user context to the request object.
import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken'
interface AuthRequest extends Request {
user?: { id: string; role: string }
}
function authenticate(req: AuthRequest, res: Response, next: NextFunction): void {
const header = req.headers.authorization
if (!header?.startsWith('Bearer ')) {
res.status(401).json({ error: 'Missing authorization header' })
return
}
const token = header.slice(7)
try {
const payload = jwt.verify(token, process.env.JWT_SECRET!) as { id: string; role: string }
req.user = { id: payload.id, role: payload.role }
next()
} catch {
res.status(401).json({ error: 'Invalid or expired token' })
}
}
function authorize(...roles: string[]) {
return (req: AuthRequest, res: Response, next: NextFunction): void => {
if (!req.user || !roles.includes(req.user.role)) {
res.status(403).json({ error: 'Insufficient permissions' })
return
}
next()
}
}Protect endpoints from abuse. Use different limits for different routes.
import rateLimit from 'express-rate-limit'
const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100,
standardHeaders: true,
legacyHeaders: false,
message: { error: 'Too many requests, try again later' },
})
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // Strict limit for auth endpoints
message: { error: 'Too many login attempts' },
})
app.use(globalLimiter)
app.use('/api/v1/auth/login', authLimiter)Configure Cross-Origin Resource Sharing for frontend clients.
import cors from 'cors'
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || []
const corsMiddleware = cors({
origin: (origin, callback) => {
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400,
})Validate request body, query, and params using Zod. Create a reusable factory.
import { z, ZodSchema } from 'zod'
import { Request, Response, NextFunction } from 'express'
function validate(schema: {
body?: ZodSchema
query?: ZodSchema
params?: ZodSchema
}) {
return (req: Request, res: Response, next: NextFunction): void => {
const errors: Record<string, unknown> = {}
if (schema.body) {
const result = schema.body.safeParse(req.body)
if (!result.success) errors.body = result.error.flatten()
}
if (schema.query) {
const result = schema.query.safeParse(req.query)
if (!result.success) errors.query = result.error.flatten()
}
if (schema.params) {
const result = schema.params.safeParse(req.params)
if (!result.success) errors.params = result.error.flatten()
}
if (Object.keys(errors).length > 0) {
res.status(400).json({ error: 'Validation failed', details: errors })
return
}
next()
}
}
// Usage
const CreateUserSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
})
router.post('/users', validate({ body: CreateUserSchema }), createUser)next() or send a response. Forgetting causes the request to hang indefinitely.(err, req, res, next). Three parameters means it is treated as regular middleware.Middleware signature: (req, res, next) => void
Error middleware: (err, req, res, next) => void
Order: parsing -> security -> rate-limit -> logging -> routes -> 404 -> errors
Route-specific: router.get('/path', middleware1, middleware2, handler)
Router-level: router.use(middleware)
App-level: app.use(middleware)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.