mcpField
C
cloudflare-workers-security

cloudflare-workers-security

github.com/secondskyセキュリティ240351 回インストール5 週間前に更新
リポジトリ

cloudflare-workers-security について

Cloudflare Workers と API の開発者向けセキュリティガイドスキルです。リクエスト検証、認証、シークレット、レート制限、ヘッダー、CORS を扱い、リファレンスとミドルウェアテンプレートも含みます。

主な機能

  1. 01リクエスト検証パターン
  2. 02JWT と API キー認証
  3. 03シークレット管理ガイド
  4. 04レート制限とセキュリティヘッダー
  5. 05CORS 設定パターン
  6. 06セキュリティ監査スクリプト

活用シーン

  1. 01Workers API の保護
  2. 02リクエスト認証の追加
  3. 03CORS 設定の確認
  4. 04一般的なセキュリティ上の問題の監査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/secondsky/claude-skills --skill cloudflare-workers-security

インストール後、Claude Code で/cloudflare-workers-securityを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
authentication.md
cors-security.md
input-validation.md
rate-limiting.md
secrets-management.md
security-headers.md
scripts/
security-audit.sh
templates/
auth-middleware.ts
cors-handler.ts
rate-limiter.ts
secure-worker.ts

詳細

Cloudflare Workers のセキュリティ

Workers と API を保護するための包括的なセキュリティパターンです。

セキュリティのクイックチェックリスト

// 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');

重要なルール

  1. クライアントからの入力を決して信頼しない - すべてを検証し、サニタイズします
  2. シークレットを安全に使用する - Wrangler のシークレットに保存し、コードには決して記述しません
  3. レート制限を実装する - 悪用を防止します
  4. セキュリティヘッダーを設定する - よくある攻撃を防止します
  5. CORS を適切に使用する - 本番環境で * を使用しないでください

よくあるセキュリティエラーのトップ 10

脆弱性症状防止策
認証の欠如不正アクセスすべてのリクエストでトークンを検証する
SQL インジェクションデータ侵害D1 ではパラメーター化クエリを使用する
XSSスクリプトの挿入出力をサニタイズし、CSP を設定する
CORS の設定ミスリクエストのブロックまたはアクセスの開放特定のオリジンを設定する
コード内のシークレット認証情報の漏えいwrangler secret を使用する
レート制限の欠如DoS の脆弱性IP ごとの制限を実装する
脆弱なトークンセッションハイジャック署名には crypto.subtle を使用する
HTTPS の欠如データの傍受HTTPS へのリダイレクトを強制する
安全でないヘッダークリックジャッキング、MIME 攻撃セキュリティヘッダーを設定する
過剰な権限被害範囲の拡大最小権限の原則を適用する

認証パターン

JWT の検証
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 キーの検証
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('');
}

入力の検証

Zod を使用する場合
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;
  }
}

セキュリティヘッダー

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 の設定

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 });
}

リファレンスを読み込むタイミング

タスクに応じて、該当するリファレンスを読み込みます。

  • 認証を実装する場合 → references/authentication.md を読み込む
  • CORS の問題がある場合 → references/cors-security.md を読み込む
  • 入力を検証する場合 → references/input-validation.md を読み込む
  • シークレットを管理する場合 → references/secrets-management.md を読み込む
  • レート制限を設定する場合 → references/rate-limiting.md を読み込む
  • セキュリティヘッダーを設定する場合 → references/security-headers.md を読み込む

テンプレート

テンプレート目的使用するタイミング
templates/auth-middleware.tsJWT/API キー認証認証を追加する場合
templates/cors-handler.tsCORS ミドルウェアクロスオリジンを処理する場合
templates/rate-limiter.tsレート制限悪用を防止する場合
templates/secure-worker.tsセキュリティ対策を網羅した設定セキュアなプロジェクトを開始する場合

スクリプト

スクリプト目的コマンド
scripts/security-audit.shセキュリティを監査する./security-audit.sh <url>

リソース

コメント