mcpField
I
input-validation

input-validation

github.com/yanko-belovセキュリティ1337 回インストール40 週間前に更新
リポジトリ

input-validation について

input-validationは、システム境界で信頼できないデータを検証するよう開発者に促すセキュリティスキルです。検証基準やスキーマを使う方法、危険な兆候、検証を省く際のよくある理由への対応をまとめています。

主な機能

  1. 01入口で外部データを検証
  2. 02型、形式、範囲、必須項目の確認
  3. 03スキーマによる検証パターン
  4. 04危険な入力処理パターンの特定
  5. 05検証を省く一般的な理由への反論

活用シーン

  1. 01データベース書き込み前のHTTPリクエスト検証
  2. 02ファイル、環境変数、API入力の確認
  3. 03未検証入力があるコードのレビュー

インストール

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

$npx skills add https://github.com/yanko-belov/code-craft --skill input-validation

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

詳細

入力検証

概要

入力を決して信頼しないでください。システム境界ですべてを検証してください。

外部データはすべて、悪意のあるデータや不正な形式のデータである可能性があります。入力時に検証し、無効な入力はすぐに拒否してください。

使用する場面

  • HTTP リクエストのボディ、パラメーター、ヘッダーを処理する場合
  • ファイルや環境変数を読み込む場合
  • 外部 API からデータを受け取る場合
  • 信頼できない入力を受け取るあらゆる関数

絶対的なルール

NEVER use external input without explicit validation.

例外はありません:

  • 「フロントエンドで検証しているから」
  • 「内部 API だから」
  • 「送信元を信頼しているから」
  • 「単純なフィールドだから」

検出:信頼上の危険信号

入力をそのまま使っているなら、STOP してください:

// ❌ VIOLATION: Trusting input
app.post('/users', async (req, res) => {
  const { email, age } = req.body;  // Direct destructure - no validation
  await db.users.create({ email, age });
  res.json({ success: true });
});

問題点:

  • email が空、null、または文字列以外の可能性があります
  • age が負の数、文字列、または未指定の可能性があります
  • 使い方によっては、SQL インジェクションや XSS が発生する可能性があります

正しいパターン:境界で検証する

// ✅ CORRECT: Validate with schema
import { z } from 'zod';

const createUserSchema = z.object({
  email: z.string().email('Invalid email format'),
  age: z.number().int().min(13).max(120),
  name: z.string().min(1).max(100),
});

app.post('/users', async (req, res) => {
  // Validate
  const result = createUserSchema.safeParse(req.body);
  
  if (!result.success) {
    return res.status(400).json({ 
      error: 'Validation failed',
      details: result.error.flatten().fieldErrors 
    });
  }
  
  // Now data is typed and validated
  const { email, age, name } = result.data;
  await db.users.create({ email, age, name });
  res.status(201).json({ success: true });
});

検証ルール

常に検証する項目:
  • 型:文字列、数値、真偽値のどれですか?
  • 形式:有効なメールアドレスですか?有効な UUID ですか?
  • 範囲:最小/最大の長さは?数値の範囲は?
  • 必須項目:値が指定されていますか?
  • サニタイズ:必要に応じて危険な文字を削除します
検証ライブラリの例:
// Zod (recommended for TypeScript)
const schema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  age: z.number().min(0).max(150),
  role: z.enum(['user', 'admin']),
  tags: z.array(z.string()).max(10),
});

// Yup
const schema = yup.object({
  email: yup.string().email().required(),
  age: yup.number().positive().integer(),
});

// class-validator
class CreateUserDto {
  @IsEmail()
  email: string;
  
  @IsInt()
  @Min(13)
  age: number;
}

圧力に負けないためのプロトコル

1. 「フロントエンドで検証しています」

圧力:「フォームですでにこのデータを検証しています」

**回答:**フロントエンドの検証は UX のためのものです。バックエンドの検証はセキュリティのためのものです。攻撃者はフロントエンドを回避します。

**対応:**フロントエンドでの検証にかかわらず、バックエンドでも検証してください。

2. 「内部 API です」

圧力:「このエンドポイントを呼び出すのは自社のサービスだけです」

**回答:**内部サービスにもバグはあります。多層防御のためには、あらゆる場所で検証が必要です。

**対応:**内部 API の入力も検証してください。

3. 「送信元を信頼しています」

圧力:「このデータはパートナーの API から来ています」

**回答:**相手の API にバグがある、侵害される、または形式が変わる可能性があります。誰も信頼しないでください。

**対応:**外部 API のレスポンスは、使用する前に検証してください。

4. 「単純なフィールドです」

圧力:「単なる文字列です。何が起きるというのですか?」

**回答:**文字列は空である、長すぎる、スクリプトや SQL、またはヌルバイトを含む可能性があります。

対応:「有効」が何を意味するかを定義し、それを徹底してください。

危険信号 — STOP して再検討する

  • 検証せずに const { x } = req.body を使う
  • 入力に any 型を使う
  • 無効な入力に対するエラーレスポンスがない
  • 「クライアントは正しい形式で送信する」
  • try/catch を使わずに入力を解析する

これらはすべて、検証を追加すべきことを意味します。

クイックリファレンス

入力の種類検証項目
Email形式、長さ、必須かどうか
Password長さ、複雑さ
ID形式(uuid/int)、存在するかどうか
Number型、範囲、整数かどうか
String長さ、パターン、サニタイズ
Array長さ、各項目の検証
Objectスキーマ検証

よくある自己正当化(すべて誤り)

言い訳実態
「フロントエンドで検証している」攻撃者はフロントエンドを回避します。
「内部 API だ」内部にもバグはあります。
「送信元を信頼している」送信元が侵害される可能性があります。
「単純なフィールドだ」単純なフィールドが複雑なバグを引き起こします。
「検証は遅い」検証は侵害よりも速く済みます。
「TypeScript の型で十分だ」型は実行時には消えます。

要点

すべての入力を検証してください。何も信頼しないでください。無効なデータはすぐに拒否してください。

すべての外部境界で明示的な検証を行う必要があります。スキーマ検証ライブラリを使用してください。無効な入力には明確なエラーメッセージを返してください。未検証のデータを決してシステムに入れないでください。

コメント