Skip to content
cccskills
FreePublished on GitHub

security-review

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

The English summary is being prepared. Showing the original description.

Works withSupabaseOpenAI
See how to install

Files included (1)

  • SKILL.md13.9 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

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

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

発動タイミング

  • 認証または認可の実装時
  • ユーザー入力やファイルアップロードの処理時
  • 新しいAPIエンドポイントの作成時
  • シークレットや認証情報の取り扱い時
  • 決済機能の実装時
  • センシティブデータの保存または送信時
  • サードパーティAPIとの統合時

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

1. シークレット管理

❌ 絶対にしてはいけないこと

const apiKey = "sk-proj-xxxxx"  // Hardcoded secret
const dbPassword = "password123" // In source code

✅ 必ず行うこと

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

// Verify secrets exist
if (!apiKey) {
  throw new Error('OPENAI_API_KEY not configured')
}

検証ステップ

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

2. 入力バリデーション

ユーザー入力は必ずバリデーション

import { z } from 'zod'

// Define validation schema
const CreateUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
  age: z.number().int().min(0).max(150)
})

// Validate before processing
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.errors }
    }
    throw error
  }
}

ファイルアップロードのバリデーション

function validateFileUpload(file: File) {
  // Size check (5MB max)
  const maxSize = 5 * 1024 * 1024
  if (file.size > maxSize) {
    throw new Error('File too large (max 5MB)')
  }

  // Type check
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
  if (!allowedTypes.includes(file.type)) {
    throw new Error('Invalid file type')
  }

  // Extension check
  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を文字列連結してはいけない

// DANGEROUS - SQL Injection vulnerability
const query = `SELECT * FROM users WHERE email = '${userEmail}'`
await db.query(query)

✅ 必ずパラメータ化クエリを使用

// Safe - parameterized query
const { data } = await supabase
  .from('users')
  .select('*')
  .eq('email', userEmail)

// Or with raw SQL
await db.query(
  'SELECT * FROM users WHERE email = $1',
  [userEmail]
)

検証ステップ

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

4. 認証と認可

JWTトークンの取り扱い

// ❌ WRONG: localStorage (vulnerable to XSS)
localStorage.setItem('token', token)

// ✅ CORRECT: httpOnly cookies
res.setHeader('Set-Cookie',
  `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)

認可チェック

export async function deleteUser(userId: string, requesterId: string) {
  // ALWAYS verify authorization first
  const requester = await db.users.findUnique({
    where: { id: requesterId }
  })

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

  // Proceed with deletion
  await db.users.delete({ where: { id: userId } })
}

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

-- Enable RLS on all tables
ALTER TABLE users ENABLE ROW LEVEL SECURITY;

-- Users can only view their own data
CREATE POLICY "Users view own data"
  ON users FOR SELECT
  USING (auth.uid() = id);

-- Users can only update their own data
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'

// ALWAYS sanitize user-provided HTML
function renderUserContent(html: string) {
  const clean = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],
    ALLOWED_ATTR: []
  })
  return <div dangerouslySetInnerHTML={{ __html: clean }} />
}

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

// next.config.js
const securityHeaders = [
  {
    key: 'Content-Security-Policy',
    value: `
      default-src 'self';
      script-src 'self' 'unsafe-eval' 'unsafe-inline';
      style-src 'self' 'unsafe-inline';
      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 }
    )
  }

  // Process request
}

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 minutes
  max: 100, // 100 requests per window
  message: 'Too many requests'
})

// Apply to routes
app.use('/api/', limiter)

コストの高い操作

// Aggressive rate limiting for searches
const searchLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 10, // 10 requests per minute
  message: 'Too many search requests'
})

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

検証ステップ

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

8. センシティブデータの露出

ログ

// ❌ WRONG: Logging sensitive data
console.log('User login:', { email, password })
console.log('Payment:', { cardNumber, cvv })

// ✅ CORRECT: Redact sensitive data
console.log('User login:', { email, userId })
console.log('Payment:', { last4: card.last4, userId })

エラーメッセージ

// ❌ WRONG: Exposing internal details
catch (error) {
  return NextResponse.json(
    { error: error.message, stack: error.stack },
    { status: 500 }
  )
}

// ✅ CORRECT: Generic error messages
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) {
  // Verify recipient
  if (transaction.to !== expectedRecipient) {
    throw new Error('Invalid recipient')
  }

  // Verify amount
  if (transaction.amount > maxAmount) {
    throw new Error('Amount exceeds limit')
  }

  // Verify user has sufficient balance
  const balance = await getBalance(transaction.from)
  if (balance < transaction.amount) {
    throw new Error('Insufficient balance')
  }

  return true
}

検証ステップ

  • ウォレット署名が検証されている
  • トランザクション詳細がバリデーションされている
  • トランザクション前の残高チェック
  • ブラインドトランザクション署名がない

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

定期的な更新

# Check for vulnerabilities
npm audit

# Fix automatically fixable issues
npm audit fix

# Update dependencies
npm update

# Check for outdated packages
npm outdated

ロックファイル

# ALWAYS commit lock files
git add package-lock.json

# Use in CI/CD for reproducible builds
npm ci  # Instead of npm install

検証ステップ

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

セキュリティテスト

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

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

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

// Test input validation
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 rate limiting
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つの脆弱性がプラットフォーム全体を危険にさらす可能性があります。迷ったときは安全側に倒してください。

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

コーディングエージェント(Claude Code、Aider、Codexなど)のカスタムタスクによる直接比較。合格率、コスト、時間、一貫性メトリクスを測定

The English summary is being prepared. Showing the original description.

hage-oyaji/everything-claude-code-jp-local3Updated Mar 29, 2026

AIエージェントのアクションスペース、ツール定義、オブザベーションフォーマットを設計・最適化し、タスク完了率を向上させる

The English summary is being prepared. Showing the original description.

hage-oyaji/everything-claude-code-jp-local3Updated Mar 29, 2026

評価ファーストの実行、分解、コスト考慮型モデルルーティングによるエージェンティックエンジニアとしての運用

The English summary is being prepared. Showing the original description.

hage-oyaji/everything-claude-code-jp-local3Updated Mar 29, 2026

AIエージェントが実装出力の大部分を生成するチームのためのエンジニアリング運用モデル

The English summary is being prepared. Showing the original description.

hage-oyaji/everything-claude-code-jp-local3Updated Mar 29, 2026

AI支援開発のためのリグレッションテスト戦略。データベース依存なしのサンドボックスモードAPIテスト、自動バグチェックワークフロー、同一モデルがコードの作成とレビューを行う際のAIの盲点を検出するパターン。

The English summary is being prepared. Showing the original description.

hage-oyaji/everything-claude-code-jp-local3Updated Mar 29, 2026

AndroidおよびKotlin Multiplatformプロジェクトのためのクリーンアーキテクチャパターン — モジュール構成、依存関係ルール、UseCase、Repository、データレイヤーパターン

The English summary is being prepared. Showing the original description.

hage-oyaji/everything-claude-code-jp-local3Updated Mar 29, 2026

See all skills by hage-oyaji

Report a problem with this skill