Communitygithub.com

セキュリティレビュー

認証の追加、ユーザー入力の処理、シークレットの取り扱い、APIエンドポイントの作成、または支払い/機密機能の実装時にこのスキルを使用します。包括的なセキュリティチェックリストとパターンを提供します。

セキュリティレビュー とは?

このスキルは、コードがセキュリティのベストプラクティスに従っていることを確認し、潜在的な脆弱性を特定するための包括的なセキュリティレビュースキルです。認証・認可の実装、ユーザー入力やファイルアップロードの処理、新しいAPIエンドポイントの作成、シークレットやクレデンシャルの取り扱い、支払い機能の実装、機密データの保存や送信、サードパーティAPIの統合など、セキュリティ上重要な局面で自動的にアクティブ化されるように設計されています。 このスキルは、シークレット管理、入力バリデーション、SQLインジェクション防止、認証・認可、XSS防止、CSRF保護など、6つの主要なセキュリティカテゴリをカバーする詳細なチェックリストを提供します。各カテゴリにおいて、安全でない実装(FAIL)と安全な実装(PASS)の具体的なコード例を示し、検証手順をリストアップしています。例えば、ハードコードされたシークレットの禁止と環境変数の使用、Zodスキーマによる入力バリデーション、パラメータ化クエリの使用、httpOnly CookieによるJWTトークンの保管、DOMPurifyによるHTMLサニタイズ、適切なCSPヘッダーの設定など、実践的なセキュリティパターンをTypeScript/JavaScriptコードとともに提供します。 このスキルは、Next.js、Supabase、および一般的なNode.jsベースの開発環境で動作するように最適化されており、AIエージェントがコード生成やレビューを行う際に、セキュリティ上の落とし穴を自動的にチェックし、安全な実装パターンを提案することができます。開発者はこのスキルを活用することで、セキュリティ専門家でなくても、プロダクション品質の安全なコードを一貫して生成することが可能になります。

対応~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/security-review

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

セキュリティレビュースキル

このスキルは、すべてのコードがセキュリティのベストプラクティスに従い、潜在的な脆弱性を特定することを保証します。

アクティブ化するタイミング

  • 認証または認可を実装する場合
  • ユーザー入力やファイルアップロードを処理する場合
  • 新しいAPIエンドポイントを作成する場合
  • シークレットや認証情報を扱う場合
  • 支払い機能を実装する場合
  • 機密データを保存または送信する場合
  • サードパーティのAPIを統合する場合

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

1. シークレット管理

失敗:絶対に行わないこと

const apiKey = "sk-proj-xxxxx"  // ハードコードされたシークレット
const dbPassword = "password123" // ソースコード内

成功:常に行うこと

const apiKey = process.env.OPENAI_API_KEY
const dbUrl = process.env.DATABASE_URL

// シークレットの存在確認
if (!apiKey) {
  throw new Error('OPENAI_API_KEY not configured')
}

確認手順

  • ハードコードされたAPIキー、トークン、パスワードがないこと
  • すべてのシークレットが環境変数にあること
  • .env.local が .gitignore に含まれていること
  • Git履歴にシークレットがないこと
  • 本番環境のシークレットがホスティングプラットフォーム(Vercel、Railway)にあること

2. 入力検証

常にユーザー入力を検証する

import { z } from 'zod'

// 検証スキーマを定義
const CreateUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
  age: z.number().int().min(0).max(150)
})

// 処理前に検証
export async function createUser(input: unknown) {
  try {
    const validated = CreateUserSchema.parse(input)
    return await db.users.create(validated)
  } catch (error) {
    if (error instanceof z.ZodError) {
      return { success: false, errors: error.issues }
    }
    throw error
  }
}

ファイルアップロードの検証

function validateFileUpload(file: File) {
  // サイズチェック(最大5MB)
  const maxSize = 5 * 1024 * 1024
  if (file.size > maxSize) {
    throw new Error('File too large (max 5MB)')
  }

  // タイプチェック
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
  if (!allowedTypes.includes(file.type)) {
    throw new Error('Invalid file type')
  }

  // 拡張子チェック
  const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif']
  const extension = file.name.toLowerCase().match(/\.[^.]+$/)?.[0]
  if (!extension || !allowedExtensions.includes(extension)) {
    throw new Error('Invalid file extension')
  }

  return true
}

確認手順

  • すべてのユーザー入力がスキーマで検証されていること
  • ファイルアップロードが制限されていること(サイズ、タイプ、拡張子)
  • クエリ内でユーザー入力を直接使用していないこと
  • ホワイトリスト検証(ブラックリストではない)
  • エラーメッセージが機密情報を漏洩しないこと

3. SQLインジェクション防止

失敗:絶対にSQLを連結しない

// 危険 - SQLインジェクションの脆弱性
const query = `SELECT * FROM users WHERE email = '${userEmail}'`
await db.query(query)

成功:常にパラメータ化クエリを使用する

// 安全 - パラメータ化クエリ
const { data } = await supabase
  .from('users')
  .select('*')
  .eq('email', userEmail)

// または、生のSQLを使用
await db.query(
  'SELECT * FROM users WHERE email = $1',
  [userEmail]
)

確認手順

  • すべてのデータベースクエリがパラメータ化クエリを使用していること
  • SQL内で文字列連結がないこと
  • ORM/クエリビルダーが正しく使用されていること
  • Supabaseクエリが適切にサニタイズされていること

4. 認証と認可

JWTトークンの取り扱い

// 失敗:間違い: localStorage(XSSに対して脆弱)
localStorage.setItem('token', token)

// 成功:正しい: httpOnly Cookie
res.setHeader('Set-Cookie',
  `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)

認可チェック

export async function deleteUser(userId: string, requesterId: string) {
  // 常に最初に認可を確認する
  const requester = await db.users.findUnique({
    where: { id: requesterId }
  })

  if (requester.role !== 'admin') {
    return NextResponse.json(
      { error: 'Unauthorized' },
      { status: 403 }
    )
  }

  // 削除を実行
  await db.users.delete({ where: { id: userId } })
}

行レベルセキュリティ(Supabase)

-- すべてのテーブルでRLSを有効化
ALTER TABLE users ENABLE ROW LEVEL SECURITY;

-- ユーザーは自分のデータのみを表示可能
CREATE POLICY "Users view own data"
  ON users FOR SELECT
  USING (auth.uid() = id);

-- ユーザーは自分のデータのみを更新可能
CREATE POLICY "Users update own data"
  ON users FOR UPDATE
  USING (auth.uid() = id);

確認手順

  • トークンがhttpOnly Cookieに保存されていること(localStorageではない)
  • 機密操作の前に認可チェックが行われていること
  • Supabaseで行レベルセキュリティが有効化されていること
  • ロールベースのアクセス制御が実装されていること
  • セッション管理が安全であること

5. XSS防止

HTMLのサニタイズ

import DOMPurify from 'isomorphic-dompurify'

// 常にユーザー提供のHTMLをサニタイズする
function renderUserContent(html: string) {
  const clean = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],
    ALLOWED_ATTR: []
  })
  return <div dangerouslySetInnerHTML={{ __html: clean }} />
}

コンテンツセキュリティポリシー

厳格に開始し、文書化された削除計画がある場合のみ緩和します。デフォルトで 'unsafe-inline' や 'unsafe-eval' を使用しないでください。これらはCSPの保護をほとんど無効にし、一時的な互換性の負債として扱うべきです。

// next.config.js
const securityHeaders = [
  {
    key: 'Content-Security-Policy',
    value: `
      default-src 'self';
      base-uri 'self';
      object-src 'none';
      frame-ancestors 'none';
      script-src 'self';
      style-src 'self';
      img-src 'self' data: https:;
      font-src 'self';
      connect-src 'self' https://api.example.com;
    `.replace(/\s{2,}/g, ' ').trim()
  }
]

確認手順

  • ユーザー提供のHTMLがサニタイズされていること
  • CSPヘッダーが設定されていること
  • 未検証の動的コンテンツレンダリングがないこと
  • Reactの組み込みXSS保護が使用されていること

6. CSRF対策

CSRFトークン

import { csrf } from '@/lib/csrf'

export async function POST(request: Request) {
  const token = request.headers.get('X-CSRF-Token')

  if (!csrf.verify(token)) {
    return NextResponse.json(
      { error: 'Invalid CSRF token' },
      { status: 403 }
    )
  }

  // リクエストを処理
}

SameSite Cookie

res.setHeader('Set-Cookie',
  `session=${sessionId}; HttpOnly; Secure; SameSite=Strict`)

確認手順

  • 状態変更操作にCSRFトークンを使用していること
  • すべてのCookieに SameSite=Strict が設定されていること
  • ダブルサブミットCookieパターンが実装されていること

7. レート制限

APIレート制限

import rateLimit from 'express-rate-limit'

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分間
  max: 100, // ウィンドウあたり100リクエスト
  message: 'Too many requests'
})

// ルートに適用
app.use('/api/', limiter)

コストの高い操作

// 検索に対する積極的なレート制限
const searchLimiter = rateLimit({
  windowMs: 60 * 1000, // 1分間
  max: 10, // 1分あたり10リクエスト
  message: 'Too many search requests'
})

app.use('/api/search', searchLimiter)

確認手順

  • すべてのAPIエンドポイントにレート制限が設定されていること
  • コストの高い操作に対してより厳しい制限が設定されていること
  • IPベースのレート制限
  • ユーザーベースのレート制限(認証済み)

8. 機密データの露出

ロギング

// 失敗:間違い: 機密データのロギング
console.log('User login:', { email, password })
console.log('Payment:', { cardNumber, cvv })

// 成功:正しい: 機密データをマスク
console.log('User login:', { email, userId })
console.log('Payment:', { last4: card.last4, userId })

エラーメッセージ

// 失敗:間違い: 内部詳細の露出
catch (error) {
  return NextResponse.json(
    { error: error.message, stack: error.stack },
    { status: 500 }
  )
}

// 成功:正しい: 一般的なエラーメッセージ
catch (error) {
  console.error('Internal error:', error)
  return NextResponse.json(
    { error: 'An error occurred. Please try again.' },
    { status: 500 }
  )
}

確認手順

  • ログにパスワード、トークン、シークレットがないこと
  • エラーメッセージがユーザーに対して一般的であること
  • 詳細なエラーはサーバーログのみに記録されること
  • スタックトレースがユーザーに公開されないこと

9. ブロックチェーンセキュリティ(Solana)

ウォレット検証

import { verify } from '@solana/web3.js'

async function verifyWalletOwnership(
  publicKey: string,
  signature: string,
  message: string
) {
  try {
    const isValid = verify(
      Buffer.from(message),
      Buffer.from(signature, 'base64'),
      Buffer.from(publicKey, 'base64')
    )
    return isValid
  } catch (error) {
    return false
  }
}

トランザクション検証

async function verifyTransaction(transaction: Transaction) {
  // 受信者を検証
  if (transaction.to !== expectedRecipient) {
    throw new Error('Invalid recipient')
  }

  // 金額を検証
  if (transaction.amount > maxAmount) {
    throw new Error('Amount exceeds limit')
  }

  // ユーザーに十分な残高があるか確認
  const balance = await getBalance(transaction.from)
  if (balance < transaction.amount) {
    throw new Error('Insufficient balance')
  }

  return true
}

確認手順

  • ウォレット署名が検証されていること
  • トランザクション詳細が検証されていること
  • トランザクション前に残高チェックが行われていること
  • 盲目的なトランザクション署名がないこと

10. 依存関係のセキュリティ

定期的な更新

# 脆弱性をチェック
npm audit

# 自動的に修正可能な問題を修正
npm audit fix

# 依存関係を更新
npm update

# 古いパッケージをチェック
npm outdated

ロックファイル

# 常にロックファイルをコミット
chmod +w package-lock.json
git add package-lock.json

# CI/CDで再現可能なビルドに使用
npm ci  # npm install の代わりに

確認手順

  • 依存関係が最新であること
  • 既知の脆弱性がないこと(npm audit clean)
  • ロックファイルがコミットされていること
  • GitHubでDependabotが有効化されていること
  • 定期的なセキュリティ更新

セキュリティテスト

自動化されたセキュリティテスト

// 認証テスト
test('requires authentication', async () => {
  const response = await fetch('/api/protected')
  expect(response.status).toBe(401)
})

// 認可テスト
test('requires admin role', async () => {
  const response = await fetch('/api/admin', {
    headers: { Authorization: `Bearer ${userToken}` }
  })
  expect(response.status).toBe(403)
})

// 入力検証テスト
test('rejects invalid input', async () => {
  const response = await fetch('/api/users', {
    method: 'POST',
    body: JSON.stringify({ email: 'not-an-email' })
  })
  expect(response.status).toBe(400)
})

// レート制限テスト
test('enforces rate limits', async () => {
  const requests = Array(101).fill(null).map(() =>
    fetch('/api/endpoint')
  )

  const responses = await Promise.all(requests)
  const tooManyRequests = responses.filter(r => r.status === 429)

  expect(tooManyRequests.length).toBeGreaterThan(0)
})

デプロイ前のセキュリティチェックリスト

本番環境にデプロイする前に:

  • シークレット: ハードコードされたシークレットがなく、すべて環境変数にあること
  • 入力検証: すべてのユーザー入力が検証されていること
  • SQLインジェクション: すべてのクエリがパラメータ化されていること
  • XSS: ユーザーコンテンツがサニタイズされていること
  • CSRF: 保護が有効化されていること
  • 認証: 適切なトークン管理
  • 認可: ロールチェックが設定されていること
  • レート制限: すべてのエンドポイントで有効化されていること
  • HTTPS: 本番環境で強制されていること
  • セキュリティヘッダー: CSP、X-Frame-Optionsが設定されていること
  • エラー処理: エラーに機密データが含まれていないこと
  • ロギング: 機密データがログに記録されていないこと
  • 依存関係: 最新で、脆弱性がないこと
  • 行レベルセキュリティ: Supabaseで有効化されていること
  • CORS: 適切に設定されていること
  • ファイルアップロード: 検証されていること(サイズ、タイプ)
  • ウォレット署名: 検証されていること(ブロックチェーンの場合)

リソース


覚えておいてください:セキュリティはオプションではありません。1つの脆弱性がプラットフォーム全体を危険にさらす可能性があります。迷った場合は、慎重すぎるくらいで対応してください。

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

関連スキル