Skip to main content

cloudflare-workers-security

Cloudflare Workers security with authentication, CORS, rate limiting, input validation. Use for securing APIs, JWT/API keys, or encountering auth failures, CORS errors, XSS/injection vulnerabilities.

소스 정보

저장소
secondsky/claude-skills
최근 소스 활동
2026년 8월 4일 00:02
감지된 SKILL.md 언어
영어
스타
231
포크
32

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
12 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
cloudflare-workers-security
description
Cloudflare Workers security with authentication, CORS, rate limiting, input validation. Use for securing APIs, JWT/API keys, or encountering auth failures, CORS errors, XSS/injection vulnerabilities.
license
MIT
# Cloudflare Workers Security Comprehensive security patterns for protecting Workers and APIs. ## Quick Security Checklist ```typescript // 1. Validate all input const validated = schema.parse(await request.json()); // 2. Authenticate requests const user = await verifyToken(request.headers.get('Authorization')); if (!user) return new Response('Unauthorized', { status: 401 }); // 3. Rate limit const limited = await rateLimiter.check(clientIP); if (!limited.allowed) return new Response('Too Many Requests', { status: 429 }); // 4. Add security headers response.headers.set('X-Content-Type-Options', 'nosniff'); response.headers.set('X-Frame-Options', 'DENY'); // 5. Use HTTPS-only cookies headers.set('Set-Cookie', 'session=xxx; Secure; HttpOnly; SameSite=Strict'); ``` ## Critical Rules 1. **Never trust client input** - Validate and sanitize everything 2. **Use secure secrets** - Store in Wrangler secrets, never in code 3. **Implement rate limiting** - Protect against abuse 4. **Set security headers** - Prevent common attacks 5. **Use CORS properly** - Don't use `*` in production ## Top 10 Security Errors | Vulnerability | Symptom | Prevention | |---------------|---------|------------| | Missing auth | Unauthorized access | Verify tokens on every request | | SQL injection | Data breach | Use parameterized queries with D1 | | XSS | Script injection | Sanitize output, set CSP | | CORS misconfiguration | Blocked requests or open access | Configure specific origins | | Secrets in code | Exposed credentials | Use `wrangler secret` | | Missing rate limits | DoS vulnerability | Implement per-IP limits | | Weak tokens | Session hijacking | Use crypto.subtle for signing | | Missing HTTPS | Data interception | Enforce HTTPS redirects | | Insecure headers | Clickjacking, MIME attacks | Set security headers | | Excessive permissions | Blast radius | Principle of least privilege | ## Authentication Patterns ### JWT Verification ```typescript async function verifyJWT(token: string, secret: string): Promise<{ valid: boolean; payload?: unknown }> { try { const [headerB64, payloadB64, signatureB64] = token.split('.'); // Verify signature const key = await crypto.subtle.importKey( 'raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['verify'] ); const signature = Uint8Array.from(atob(signatureB64.replace(/-/g, '+').replace(/_/g, '/')), c => c.charCodeAt(0)); const data = new TextEncoder().encode(`${headerB64}.${payloadB64}`); const valid = await crypto.subtle.verify('HMAC', key, signature, data); if (!valid) return { valid: false }; // Decode payload const payload = JSON.parse(atob(payloadB64.replace(/-/g, '+').replace(/_/g, '/'))); // Check expiration if (payload.exp && Date.now() / 1000 > payload.exp) { return { valid: false }; } return { valid: true, payload }; } catch { return { valid: false }; } } ``` ### API Key Validation ```typescript async function validateApiKey( request: Request, env: Env ): Promise<{ valid: boolean; clientId?: string }> { const apiKey = request.headers.get('X-API-Key'); if (!apiKey) return { valid: false }; // Hash the key for lookup (never store plain keys) const keyHash = await sha256(apiKey); // Lookup in KV or D1 const client = await env.KV.get(`apikey:${keyHash}`, 'json'); if (!client) return { valid: false }; return { valid: true, clientId: client.id }; } async function sha256(str: string): Promise<string> { const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str)); return [...new Uint8Array(buffer)].map(b => b.toString(16).padStart(2, '0')).join(''); } ``` ## Input Validation ### With Zod ```typescript import { z } from 'zod'; const UserSchema = z.object({ name: z.string().min(1).max(100), email: z.email(), age: z.number().int().min(0).max(150).optional(), }); async function handleCreate(request: Request): Promise<Response> { try { const body = await request.json(); const user = UserSchema.parse(body); // Safe to use validated data return Response.json({ success: true, user }); } catch (error) { if (error instanceof z.ZodError) { return Response.json({ error: 'Validation failed', details: error.errors }, { status: 400 }); } throw error; } } ``` ## Security Headers ```typescript function addSecurityHeaders(response: Response): Response { const headers = new Headers(response.headers); // Prevent MIME type sniffing headers.set('X-Content-Type-Options', 'nosniff'); // Prevent clickjacking headers.set('X-Frame-Options', 'DENY'); // XSS protection headers.set('X-XSS-Protection', '1; mode=block'); // Content Security Policy headers.set('Content-Security-Policy', "default-src 'self'; script-src 'self'"); // HSTS headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); // Referrer policy headers.set('Referrer-Policy', 'strict-origin-when-cross-origin'); return new Response(response.body, { status: response.status, headers }); } ``` ## CORS Configuration ```typescript const ALLOWED_ORIGINS = ['https://app.example.com', 'https://admin.example.com']; function handleCORS(request: Request, response: Response): Response { const origin = request.headers.get('Origin'); if (!origin || !ALLOWED_ORIGINS.includes(origin)) { return response; // No CORS headers } const headers = new Headers(response.headers); headers.set('Access-Control-Allow-Origin', origin); headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization'); headers.set('Access-Control-Allow-Credentials', 'true'); headers.set('Access-Control-Max-Age', '86400'); return new Response(response.body, { status: response.status, headers }); } ``` ## When to Load References Load specific references based on the task: - **Implementing authentication?** → Load `references/authentication.md` - **CORS issues?** → Load `references/cors-security.md` - **Validating input?** → Load `references/input-validation.md` - **Managing secrets?** → Load `references/secrets-management.md` - **Rate limiting?** → Load `references/rate-limiting.md` - **Security headers?** → Load `references/security-headers.md` ## Templates | Template | Purpose | Use When | |----------|---------|----------| | `templates/auth-middleware.ts` | JWT/API key auth | Adding authentication | | `templates/cors-handler.ts` | CORS middleware | Handling cross-origin | | `templates/rate-limiter.ts` | Rate limiting | Preventing abuse | | `templates/secure-worker.ts` | Full secure setup | Starting secure project | ## Scripts | Script | Purpose | Command | |--------|---------|---------| | `scripts/security-audit.sh` | Audit security | `./security-audit.sh <url>` | ## Resources - Security: https://developers.cloudflare.com/workers/platform/security/ - WAF: https://developers.cloudflare.com/waf/ - Rate Limiting: https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/
GitHub에서 보기