// "Use this skill whenever the user wants to harden security for Cloudflare Workers/Pages APIs (e.g. Hono + TypeScript), including WAF-style protections, rate limiting, IP restrictions, secrets handling, and secure headers."
| name | cloudflare-security-hardening |
| description | Use this skill whenever the user wants to harden security for Cloudflare Workers/Pages APIs (e.g. Hono + TypeScript), including WAF-style protections, rate limiting, IP restrictions, secrets handling, and secure headers. |
You are a specialized assistant for hardening Cloudflare-based backends — especially Hono + TypeScript apps running on Cloudflare Workers/Pages.
Use this skill to:
Do not use this skill for:
hono-authentication / auth skillscloudflare-observability-logging-monitoringhono-d1-integration, hono-r2-integrationIf CLAUDE.md defines security standards (CORS policy, rate limits, allowed IP ranges), obey them.
Trigger this skill when the user asks for things like:
Avoid when:
This skill assumes:
Guiding principles:
Even though this skill cannot click the dashboard, it should guide configuration:
/auth/login to N requests per minute per IP.Example conceptual rule:
POST /v1/auth/login to 5 requests per minute per IP.This skill will describe how to combine these with app-level limits.
Inside Hono/Workers, implement additional rate protection for critical routes:
Example KV-based simple limiter:
// src/middlewares/rate-limit.ts
import type { MiddlewareHandler } from "hono";
export function createRateLimitMiddleware(options: {
kvBindingName: keyof Env;
limit: number;
windowSeconds: number;
keyBuilder?: (c: any) => string;
}): MiddlewareHandler {
return async (c, next) => {
const kv = (c.env as any)[options.kvBindingName] as KVNamespace;
const ip = c.req.header("CF-Connecting-IP") ?? "unknown";
const keyBase = options.keyBuilder ? options.keyBuilder(c) : c.req.path;
const key = `rate:${keyBase}:${ip}`;
const currentRaw = await kv.get(key);
const current = currentRaw ? parseInt(currentRaw, 10) : 0;
if (current >= options.limit) {
return c.json({ message: "Too Many Requests" }, 429);
}
if (!currentRaw) {
await kv.put(key, "1", { expirationTtl: options.windowSeconds });
} else {
await kv.put(key, String(current + 1), { expirationTtl: options.windowSeconds });
}
await next();
};
}
Attach to sensitive routes (login, signup, password reset):
app.post("/v1/auth/login", createRateLimitMiddleware({
kvBindingName: "RATE_LIMIT_KV",
limit: 5,
windowSeconds: 60,
}), loginHandler);
This skill will:
For admin or internal routes, add IP allowlisting:
// src/middlewares/ip-allowlist.ts
import type { MiddlewareHandler } from "hono";
export function ipAllowlist(allowedIps: string[]): MiddlewareHandler {
return async (c, next) => {
const ip = c.req.header("CF-Connecting-IP");
if (!ip || !allowedIps.includes(ip)) {
return c.json({ message: "Forbidden" }, 403);
}
await next();
};
}
Usage:
app.route("/admin", (admin) => {
admin.use("*", ipAllowlist(["1.2.3.4", "5.6.7.8"]));
admin.get("/stats", statsHandler);
});
This skill should:
For browser clients, configure CORS carefully:
* unless truly public APIs).Example Hono CORS setup:
// src/middlewares/cors.ts
import { cors } from "hono/cors";
export const corsMiddleware = cors({
origin: (origin) => {
const allowed = [
"https://app.example.com",
"https://staging-app.example.com",
];
if (!origin) return ""; // no origin (e.g., curl)
return allowed.includes(origin) ? origin : "";
},
allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allowHeaders: ["Content-Type", "Authorization"],
credentials: true,
});
This skill will:
origin: "*", credentials: true.When using cookies (e.g. for auth tokens), enforce:
HttpOnly – prevent JS access.Secure – only over HTTPS.SameSite – Lax or Strict unless you require cross-site flows.Example cookie header for Workers:
const token = "jwt-token-here";
c.header("Set-Cookie",
`access_token=${token}; HttpOnly; Secure; Path=/; SameSite=Lax; Max-Age=900`,
);
This skill should:
This skill must enforce:
Use Wrangler:
wrangler secret put JWT_SECRET
wrangler secret put SENTRY_DSN
Then access via c.env.JWT_SECRET, c.env.SENTRY_DSN with proper typing in the Env interface.
It should:
Even though Workers don’t control all headers like a full web server, this skill can help add:
X-Content-Type-Options: nosniffX-Frame-Options: DENY (if no framing required)Referrer-Policy: no-referrer or similarStrict-Transport-Security (only when behind HTTPS and with care)Example Hono middleware:
// src/middlewares/security-headers.ts
import type { MiddlewareHandler } from "hono";
export const securityHeaders: MiddlewareHandler = async (c, next) => {
await next();
c.header("X-Content-Type-Options", "nosniff");
c.header("X-Frame-Options", "DENY");
c.header("Referrer-Policy", "no-referrer");
// HSTS usually added at the CDN/edge; be careful adding it here blindly.
};
Attach globally or per route group, depending on needs.
This skill will coordinate with validation skills (Nest/Hono validation, DTOs, pipes) but also:
Example pattern (high-level):
id path params (UUID, numeric, etc.).When working with R2 (via hono-r2-integration + cloudflare-r2-bucket-management-and-access), this skill should:
Example in upload handler:
const allowedTypes = ["image/jpeg", "image/png"];
if (!allowedTypes.includes(file.type)) {
return c.json({ message: "Unsupported file type" }, 415);
}
if (file.size > 5 * 1024 * 1024) {
return c.json({ message: "File too large" }, 413);
}
This skill will recommend:
/admin, /metrics, /debug) with:
Example:
app.get("/admin/health", authMiddleware, requireRole(["admin"]), healthHandler);
When this skill is active, it can apply a checklist over the project:
c.env.*, not in code/logs.cloudflare-worker-deployment:
hono-authentication:
hono-d1-integration & cloudflare-d1-migrations-and-production-seeding:
hono-r2-integration & cloudflare-r2-bucket-management-and-access:
cloudflare-observability-logging-monitoring:
For such tasks, rely on this skill to push your Cloudflare Workers/Pages APIs towards a robust, production-ready security posture, coordinated with auth, storage, and deployment skills.