opengrep について
Opengrepは、Semgrepからフォークされたオープンソースの静的解析・構造的コード検索CLIです。Semgrepのルールを活用し、セキュリティ問題のスキャンやコードパターンの検索を行えます。
主な機能
- 01ASTベースの構造的コード検索
- 02ルールセットによるセキュリティスキャン
- 03カスタムYAMLルールと taint analysis
- 04SARIF・JSON形式での出力
- 05ルールのテストと検証
- 06Windows対応
活用シーン
- 01テキスト検索のノイズを抑えた特定呼び出しの検索
- 02一般的な脆弱性のコードスキャン
- 03信頼できないデータから危険な処理への追跡
- 04カスタムルール適用前のテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ opengrep/ skills --skill opengrepインストール後、Claude Code で/opengrepを入力して読み込まれたか確認します。
詳細
Opengrep 静的解析
Opengrep は、Semgrep からフォークされた、コミュニティが保守するオープンソースの静的解析ツールです。同じルール構文と CLI インターフェイスを使用しているため、既存の Semgrep ルールや知識を引き継ぐことができます。
2 つのユースケース
1. セマンティックなコード検索(grep の代替)
コードベースを調べる際、grep はテキストパターンを検索しますが、構造パターンは見逃します。Opengrep はコード構造を理解します。
| タスク | Grep | Opengrep |
|---|---|---|
| テキスト「execute」を検索する | 高速で、問題なく動作します | 過剰な機能です |
cursor.execute(...) の呼び出しを検索する | コメントや文字列にも一致する場合があります | 実際の呼び出しのみに一致します |
os.system を呼び出す関数を検索する | 困難です | pattern-inside + pattern |
| パラメーター化されていない SQL クエリを検索する | ほぼ不可能です | 汚染モード |
Opengrep を使う場合:
- 特定の引数を持つ関数やメソッドの呼び出しを検索する必要がある場合
- grep の誤検出が多すぎる場合(コメント、文字列、類似した名前との一致)
- 特定のコンテキスト内(ループ内、try ブロック内など)のパターンを検索する必要がある場合
- パターンが単なるテキストではなく、構造的な意味を持つ場合
grep を使い続ける場合:
- 単純なテキスト検索
- 速度が重要な場合
- パターンがリテラル文字列または単純な正規表現の場合
2. セキュリティスキャン
ルールセットを実行して、脆弱性や安全でないパターンを検出します。
インストール
Linux / macOS
curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash
Windows(PowerShell)
irm https://raw.githubusercontent.com/opengrep/opengrep/main/install.ps1 | iex
手動インストール
バイナリをリリースページからダウンロードします。
動作確認
opengrep --version
macOS、Linux、Windows 用の自己完結型バイナリを利用できます。Python は不要です。
opengrep scan --help を実行して、利用可能なすべてのオプションとフラグを確認してください。
コード検索パターン
すぐ使えるワンライナー
# Find all calls to a function
opengrep scan -e 'dangerous_function(...)' -l python .
# Find method calls on specific objects
opengrep scan -e '$OBJ.execute(...)' -l python .
# Find assignments to a variable name
opengrep scan -e '$VAR = os.environ.get(...)' -l python .
# Find function definitions
opengrep scan -e 'def $FUNC(...): ...' -l python .
パフォーマンスに関する注意
Opengrep はファイル全体を AST に解析します。すばやいテキスト検索には、grep のほうが 10~100 倍高速です。構造的な一致がオーバーヘッドに見合う場合に Opengrep を使ってください。
セキュリティスキャン
クイックスキャン
# Scan with a ruleset
opengrep scan --config p/security-audit .
# Multiple rulesets
opengrep scan --config p/security-audit --config p/owasp-top-ten .
# Scan specific paths
opengrep scan --config p/python src/
出力形式
# SARIF for tooling
opengrep scan --config p/default --sarif -o results.sarif .
# JSON for automation
opengrep scan --config p/default --json -o results.json .
# Show data flow traces
opengrep scan --dataflow-traces -f rule.yaml .
# Include enclosing context (function/class) in JSON output (experimental)
opengrep scan --output-enclosing-context --json -f rule.yaml . --experimental
フィルタリング
# By severity
opengrep scan --config p/default --severity ERROR .
# By path
opengrep scan --config p/default --include='src/**' --exclude='**/test/**' .
# Apply exclusions to explicitly passed file targets (not just directory scan roots)
opengrep scan --force-exclude --exclude='**/vendor/**' -f rule.yaml vendor/lib.py
ファイル内の関数間での汚染追跡
Opengrep は、ファイル内の関数間で汚染を追跡できます。
opengrep scan --taint-intrafile -f taint-rule.yaml .
これにより、高階関数をサポートできます。また、Semgrep Pro の --pro-intrafile と同様の機能です。
カスタムルールの作成
基本的なルール構造
rules:
- id: hardcoded-secret
languages: [python]
message: "Hardcoded secret detected in $VAR"
severity: ERROR
patterns:
- pattern: $VAR = "$VALUE"
- metavariable-regex:
metavariable: $VALUE
regex: ^sk_live_
ルール ID の一意性
重要:設定内のすべてのルールで、ルール ID は一意でなければなりません。複数のルールで同じ ID を使うと、ルールの読み込み時に重複排除されるため、1 つしか使用されません。
これは、複数の言語向けのルールを作成する際に特に重要です。ルールの対象言語が異なっていても、同じルール ID を再利用することはできません。
# WRONG - both rules have id: taint, only one will be active
rules:
- id: taint
languages: [python]
pattern: dangerous_call(...)
# ...
- id: taint
languages: [rust]
pattern: unsafe_fn(...)
# ...
# CORRECT - unique IDs for each rule
rules:
- id: taint-python-dangerous-call
languages: [python]
pattern: dangerous_call(...)
# ...
- id: taint-rust-unsafe-fn
languages: [rust]
pattern: unsafe_fn(...)
# ...
衝突を避けるため、言語やコンテキストを含む説明的な ID を使用してください。
パターン構文
| 構文 | 意味 |
|---|---|
... | 0 個以上の引数/文に一致します |
$VAR | メタ変数(任意の式をキャプチャします) |
$...ARGS | 省略記号メタ変数(0 個以上をキャプチャします) |
<... $X ...> | 深い式の一致(ネストされた式) |
パターン演算子
| 演算子 | 用途 |
|---|---|
pattern | パターンに完全一致 |
patterns | すべてに一致(AND) |
pattern-either | いずれかに一致(OR) |
pattern-not | 一致するものを除外 |
pattern-inside | コンテキスト内であること |
pattern-not-inside | コンテキスト内でないこと |
pattern-regex | 正規表現による一致 |
metavariable-regex | 正規表現でキャプチャ値をフィルタリング |
metavariable-comparison | キャプチャ値を比較 |
パターンの組み合わせ
rules:
- id: dangerous-deserialization
languages: [python]
message: "Unsafe pickle load on potentially untrusted data"
severity: ERROR
patterns:
- pattern-either:
- pattern: pickle.load(...)
- pattern: pickle.loads(...)
- pattern-not-inside: |
def $FUNC(...):
...
汚染モード
ソースからシンクへのデータフローを追跡するには、次のようにします。
rules:
- id: sql-injection
languages: [python]
message: "User input flows to SQL query without parameterization"
severity: ERROR
mode: taint
pattern-sources:
- pattern: request.args.get(...)
- pattern: request.form[...]
pattern-sinks:
- pattern: cursor.execute($QUERY, ...)
focus-metavariable: $QUERY
pattern-sanitizers:
- pattern: int(...)
- pattern: escape(...)
主な汚染の概念:
- ソース:信頼できないデータが入る場所
- シンク:データが危険になる場所
- サニタイザー:データを安全にするもの
YAML の注意点
パターンは YAML の文字列値です。: (コロンとスペース)を含むパターンは YAML マッピングとして誤って解釈され、検証エラーの原因になります。このようなパターンは必ず引用符で囲んでください。
# BROKEN -- YAML parser sees "shell: true" as a nested mapping
- pattern: spawn($CMD, { ..., shell: true, ... })
# CORRECT -- quoted string, parsed as a single pattern value
- pattern: "spawn($CMD, { ..., shell: true, ... })"
よくある例:shell: true、mode: 0o777、redirect: "follow"、error: $ERR。迷った場合は、パターンを引用符で囲んでください。
二重引用符とコロンの両方を含むパターンでは、内側の引用符をエスケープしてください。
- pattern: "fetch($URL, { ..., redirect: \"follow\", ... })"
コード以外のファイルのスキャン(汎用言語)
XML 設定、YAML パイプライン、Dockerfile、その他のコード以外のファイルでは、構造パターンが機能しないことがあります。languages: [generic] と pattern-regex を使用してください。
rules:
- id: cleartext-traffic
patterns:
- pattern-regex: 'cleartextTrafficPermitted\s*=\s*"true"'
languages: [generic]
severity: WARNING
paths:
include:
- "app/src/"
paths キーを使うと、ルールが適用されるファイルを制限できます。
paths:
include:
- ".github/workflows/" # Only scan GHA workflow files
exclude:
- "test/" # Skip test directories
注:languages: [dockerfile] は存在しますが、複数の Dockerfile ディレクティブにまたがる場合、pattern-not-inside は安定して機能しません。複数行にまたがる Dockerfile のセキュリティチェックには、generic と正規表現の組み合わせを推奨します。
metavariable-pattern
metavariable-pattern を使用すると、メタ変数が一致できる対象を絞り込めます。これは patterns: 内のリスト項目として、メタ変数をキャプチャするパターンと並べて指定する必要があります。
rules:
- id: dynamic-property-assignment
patterns:
- pattern: $OBJ[$KEY] = $VALUE
- metavariable-pattern:
metavariable: $KEY
patterns:
- pattern-not: "..." # Exclude literal string keys
languages: [typescript, javascript]
severity: WARNING
これは、パターンではなく正規表現でフィルタリングする metavariable-regex とは異なります。
パターン解析の制限
一部の言語構文は、単独の断片として一致させることができません。
catchブロック:catch ($ERR) { ... }だけでは無効です。tryを含める必要があります:try { ... } catch ($ERR) { ... }。それでも、TypeScript では catch 本体内の複雑な省略記号を解析できない場合があります。- 回避策:try/catch のコンテキストで囲むのではなく、危険な式を直接一致させてください。
ルールオプション(Opengrep 固有)
rules:
- id: expensive-rule
options:
timeout: 10 # Per-rule timeout (requires --allow-rule-timeout-control)
dynamic_timeout: true # Scale timeout with file size
max_match_per_file: 100 # Limit matches per file
# ... rest of rule
ルールごとのタイムアウトを有効にするには、--allow-rule-timeout-control を使用します。
ルールのテスト
テストファイルの注釈
期待される検出箇所の直前の行に # ruleid: を配置します(汚染ルールの場合は、シンクの直前に配置します)。
# test_rule.py
def vulnerable():
user_id = request.args.get("id")
# ruleid: sql-injection
cursor.execute("SELECT * FROM users WHERE id = " + user_id)
def safe():
user_id = int(request.args.get("id"))
# ok: sql-injection
cursor.execute("SELECT * FROM users WHERE id = " + user_id)
テストの実行
# Test a rule (supports multiple target files)
opengrep test --config rule.yaml test_file.py test_file2.py
# Validate rule syntax (positional argument, not --config)
opengrep validate rule.yaml
# Debug taint flow
opengrep scan --dataflow-traces -f rule.yaml test_file.py
設定
.semgrepignore
Opengrep は互換性のために .semgrepignore を使用します。ファイル名をカスタマイズするには、--semgrepignore-filename を指定します。
# Ignore directories
vendor/
node_modules/
**/testdata/
# Ignore patterns
*.min.js
*.generated.go
インライン抑制
デフォルトの注釈は nosemgrep、nosem、noopengrep です(いずれも機能します)。
password = get_from_vault() # nosemgrep: hardcoded-password
password = get_from_vault() # nosem: hardcoded-password
password = get_from_vault() # noopengrep: hardcoded-password
--opengrep-ignore-pattern を使用すると、追加のパターンを指定できます。
# Add nosec as an additional suppression annotation
opengrep scan --opengrep-ignore-pattern='nosec' -f rule.yaml .
ルールのメタデータ
rules:
- id: command-injection
metadata:
category: security
subcategory:
- vuln # vuln = confirmed vulnerability, audit = needs review
cwe:
- "CWE-78: Improper Neutralization of Special Elements used in an OS Command"
owasp:
- "A03:2021 - Injection"
confidence: HIGH # HIGH, MEDIUM, or LOW
references:
- https://owasp.org/Top10/A03_2021-Injection/
# ... rest of rule
category/subcategory/confidence フィールドは、ツールによる検出結果の分類とフィルタリングに使用されます。確度の高い脆弱性には subcategory: [vuln] を、手動レビューが必要なパターンには subcategory: [audit] を使用してください。
メタデータの出力にメタ変数の値を含めるには、--inline-metavariables を使用します。
一般的なルールセット
| ルールセット | 対象 |
|---|---|
p/security-audit | 包括的なセキュリティルール |
p/owasp-top-ten | OWASP Top 10 の脆弱性 |
p/cwe-top-25 | CWE Top 25 の脆弱性 |
p/python / p/javascript / p/golang | 言語固有 |
注:ルールセットの利用可否は Semgrep レジストリとは異なる場合があります。
Semgrep との違い
Opengrep は Semgrep 1.100.0 からフォークされました。主な違いは次のとおりです。
- Semgrep Pro の機能をオープンに提供:ファイル内の関数間の taint 解析(
--taint-intrafile)、高階関数のサポート、メソッド間の taint フローを、商用ライセンスなしで利用できます - 追加の言語:Visual Basic(Semgrep CE または Pro では利用できません)、Apex、Elixir(Semgrep CE では利用できません)、taint サポートが強化された Clojure
- Windows:ネイティブサポート
- ルールごとのタイムアウト:ルールオプションの
timeoutとdynamic_timeout - 一致数の上限:ルールオプションの
max_match_per_fileと CLI フラグの--max-match-per-file - コンテキストの出力:
--output-enclosing-contextで関数/クラスのコンテキストを表示します - カスタムの無視パターン:
--opengrep-ignore-patternでデフォルトの抑制設定を拡張します
変更履歴の全文は、こちらを参照してください:https://github.com/opengrep/opengrep/blob/main/OPENGREP.md
既存の Semgrep ルールとドキュメントは、通常そのまま適用できます。
リソース
- Opengrep:https://github.com/opengrep/opengrep
- Semgrep ルール構文(互換性あり):https://semgrep.dev/docs/writing-rules/rule-syntax