mcpField
E
error-pattern-safety

error-pattern-safety

github.com/github開発5.5k61 回インストール今日更新
リポジトリ

error-pattern-safety について

エージェントエンジンのエラー正規表現を扱う開発者向けガイドです。JavaScript のグローバル正規表現がゼロ幅一致でループする問題を防ぐルールとテスト方法を示します。

主な機能

  1. 01ゼロ幅正規表現の一致を回避
  2. 02パターンに実文字を必須化
  3. 03空文字列との一致を検査
  4. 04Go から JavaScript への変換を説明
  5. 05検証テストの指針を提示

活用シーン

  1. 01エンジンの新しいエラーパターンの確認
  2. 02JavaScript 正規表現のループリスク調査
  3. 03JavaScript 検証用の Go パターン変換

インストール

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

$npx skills add https://github.com/github/gh-aw --skill error-pattern-safety

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

詳細

エラーパターンの安全性に関するガイドライン

JavaScript の無限ループを防ぐため、エージェント型エンジンでは以下の正規表現の安全ルールに従ってください。

問題点

JavaScript のグローバルフラグ(/pattern/g)を使うと、ゼロ幅マッチによって無限ループが発生することがあります。その理由は次のとおりです。

  1. JavaScript の regex.exec() は g フラグを使うと、位置の追跡に lastIndex を使用します
  2. パターンがゼロ幅にマッチすると、lastIndex は進みません
  3. 同じ位置に繰り返しマッチし、無限ループが発生します

危険なパターンの例

❌ これらのパターンは絶対に使用しないでください:

// Pure .* - matches everything including empty string at end
/.*/g

// Single character with * - matches zero or more (including zero)
/a*/g

// Patterns that can match empty string
/(x|y)*/g

安全なパターンの例

✅ 常に次のようなパターンを使用してください:

// Required prefix before .*
/error.*/gi
/error.*permission.*denied/gi

// Specific structure with required content
/\[(\d{4}-\d{2}-\d{2})\]\s+(ERROR):\s+(.+)/g

// Required characters throughout
/access denied.*user.*not authorized/gi

パターンの安全ルール

  1. 少なくとも1文字に必ずマッチするようにする

    • 「何か」を必要とする場合は、.* ではなく .+ を使用します
    • パターンに必須のプレフィックスまたはサフィックスが含まれていることを確認します
  2. .* のみをパターン全体として使用しない

    • 必ず必須のテキストと組み合わせます:error.*
    • .* または .*? のみを使用しないでください
  3. 空文字列に対してパターンをテストする

    const regex = /your-pattern/g;
    if (regex.test("")) {
      throw new Error("Pattern matches empty string - DANGEROUS!");
    }
    
  4. 可能な場合は具体的なアンカーを使用する

    • 先頭:^error.*
    • 末尾:.*error$
    • 単語境界:\berror\b

検証テスト

すべてのエラーパターンは、以下のテストに合格する必要があります。

Go テスト(pkg/workflow/engine_error_patterns_infinite_loop_test.go)
// Test that pattern doesn't match empty string
func TestPatternSafety(t *testing.T) {
    pattern := "your-pattern"
    regex := regexp.MustCompile(pattern)
    
    if regex.MatchString("") {
        t.Error("Pattern matches empty string!")
    }
}
JavaScript テスト(pkg/workflow/js/validate_errors.test.cjs)
test("should not match empty string", () => {
  const regex = new RegExp("your-pattern", "g");
  expect(regex.test("")).toBe(false);
});

validate_errors.cjs の安全機構

validate_errors.cjs スクリプトには、次の保護機能が組み込まれています。

  1. ゼロ幅検出:regex.lastIndex の更新が停止しているかを確認します
  2. 反復警告:反復回数が1000回に達すると警告します
  3. 上限:ハングを防ぐため、反復回数が10,000回に達すると停止します
// Safety check in validate_errors.cjs
if (regex.lastIndex === lastIndex) {
  core.error(`Infinite loop detected! Pattern: ${pattern.pattern}`);
  break;
}

新しいエラーパターンの追加

エンジンに新しいエラーパターンを追加する場合は、次の手順に従ってください。

  1. 必須の内容を含むパターンを書く

    {
        Pattern:      `(?i)error.*permission.*denied`,
        LevelGroup:   0,
        MessageGroup: 0,
        Description:  "Permission denied error",
    }
    
  2. 空文字列に対してテストする

    • 実行:make test-unit
    • 確認項目:TestAllEnginePatternsSafe
  3. 実際のログサンプルでテストする

    • 実際のエラーにマッチすることを確認します
    • 情報テキストにマッチしないことを確認します
  4. パターンを説明する

    • わかりやすい説明を追加します
    • 検出対象を明記します

パターンの変換:Go から JavaScript へ

パターンは Go から JavaScript に変換されます。

// Go pattern (case-insensitive flag)
Pattern: `(?i)error.*permission.*denied`

// Converted to JavaScript
new RegExp("error.*permission.*denied", "gi")

JavaScript では代わりに i フラグを使うため、(?i) プレフィックスは削除されます。

現在のコードベースからの例

✅ 安全なパターン
// Requires "error" prefix
Pattern: `(?i)error.*permission.*denied`

// Requires specific timestamp format
Pattern: `(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)\s+\[(ERROR)\]\s+(.+)`

// Requires "access denied" prefix
Pattern: `(?i)access denied.*user.*not authorized`
危険なパターンの修正方法

空文字列にマッチするパターンが見つかった場合:

修正前(安全ではない):

Pattern: `.*error.*`  // Can match empty at start/end

修正後(安全):

Pattern: `error.*`     // Requires "error" at start
// OR
Pattern: `.*error.+`   // Requires "error" and at least one char after
// OR
Pattern: `\berror\b.*` // Requires word "error"

テストチェックリスト

パターンの変更をコミットする前に、次の項目を確認してください。

  • make test-unit を実行する
  • TestAllEnginePatternsSafe が成功することを確認する
  • TestErrorPatternsNoInfiniteLoopPotential が成功することを確認する
  • JavaScript テストを実行する:cd pkg/workflow/js && npm test
  • パターンが意図したエラーメッセージにマッチすることを確認する
  • パターンが情報テキストにマッチしないことを確認する

参考資料

コメント