implementing-semgrep-for-custom-sast-rules について
Semgrep のカスタム SAST ルールを導入するアプリケーションセキュリティおよび開発チーム向けのガイドです。YAML でのルール作成、テスト、CI/CD 連携を扱います。
主な機能
- 01カスタム YAML ルールの作成
- 02パターンと taint 解析の利用
- 03ルールテストと修正案の提示
- 04GitHub Actions と GitLab CI の連携
活用シーン
- 01組織固有のセキュリティ問題の検出
- 02CI で重大な検出結果をブロック
- 03コーディング規約の適用
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill implementing-semgrep-for-custom-sast-rulesインストール後、Claude Code で/implementing-semgrep-for-custom-sast-rulesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdstandards.mdscripts/agent.py詳細
カスタム SAST ルールの Semgrep 実装
概要
Semgrep は、パターンマッチングを使用してバグを発見し、コーディング規約を適用し、セキュリティ上の脆弱性を検出するオープンソースの静的解析ツールです。カスタムルールは Semgrep のパターン構文を使って YAML で記述するため、コンパイラーの知識がなくても利用できます。Python、JavaScript、Go、Java、C など、30 以上の言語をサポートしています。
使用する場面
- 環境において、カスタム SAST ルール向けの Semgrep 機能を導入または設定する場合
- コンプライアンス要件に沿ったセキュリティ制御を確立する場合
- この分野のセキュリティアーキテクチャを構築または改善する場合
- この実装を必要とするセキュリティ評価を実施する場合
前提条件
- Python 3.8+ または Docker
- Semgrep CLI がインストールされていること
- サポート対象の言語で書かれた対象コードベース
インストール
# Install via pip
pip install semgrep
# Install via Homebrew
brew install semgrep
# Run via Docker
docker run -v "${PWD}:/src" returntocorp/semgrep semgrep --config auto /src
# Verify
semgrep --version
Semgrep の実行
# Auto-detect rules for your code
semgrep --config auto .
# Use Semgrep registry rules
semgrep --config r/python.lang.security
# Use custom rule file
semgrep --config my-rules.yaml .
# Use multiple configs
semgrep --config auto --config ./custom-rules/ .
# JSON output
semgrep --config auto --json . > results.json
# SARIF output for GitHub
semgrep --config auto --sarif . > results.sarif
# Filter by severity
semgrep --config auto --severity ERROR .
カスタムルールの作成
基本的なパターンマッチング
# rules/sql-injection.yaml
rules:
- id: sql-injection-string-format
languages: [python]
severity: ERROR
message: |
Potential SQL injection via string formatting.
Use parameterized queries instead.
pattern: |
cursor.execute(f"..." % ...)
metadata:
cwe: ["CWE-89"]
owasp: ["A03:2021"]
category: security
fix: |
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
パターン演算子
rules:
- id: hardcoded-secret-in-code
languages: [python, javascript, typescript]
severity: ERROR
message: Hardcoded secret detected in source code
patterns:
- pattern-either:
- pattern: $VAR = "..."
- pattern: $VAR = '...'
- metavariable-regex:
metavariable: $VAR
regex: (?i)(password|secret|api_key|token|aws_secret)
- pattern-not: $VAR = ""
- pattern-not: $VAR = "changeme"
- pattern-not: $VAR = "PLACEHOLDER"
metadata:
cwe: ["CWE-798"]
category: security
汚染解析
rules:
- id: xss-taint-tracking
languages: [python]
severity: ERROR
message: User input flows to HTML response without sanitization
mode: taint
pattern-sources:
- pattern: request.args.get(...)
- pattern: request.form.get(...)
- pattern: request.form[...]
pattern-sinks:
- pattern: return render_template_string(...)
- pattern: Markup(...)
pattern-sanitizers:
- pattern: bleach.clean(...)
- pattern: escape(...)
metadata:
cwe: ["CWE-79"]
owasp: ["A03:2021"]
複数言語のルール
rules:
- id: insecure-random
languages: [python, javascript, go, java]
severity: WARNING
message: |
Using insecure random number generator. Use cryptographically
secure alternatives for security-sensitive operations.
pattern-either:
# Python
- pattern: random.random()
- pattern: random.randint(...)
# JavaScript
- pattern: Math.random()
# Go
- pattern: math/rand.Intn(...)
# Java
- pattern: new java.util.Random()
metadata:
cwe: ["CWE-330"]
コーディング規約の適用
rules:
- id: require-error-handling
languages: [go]
severity: WARNING
message: Error return value not checked
pattern: |
$VAR, _ := $FUNC(...)
fix: |
$VAR, err := $FUNC(...)
if err != nil {
return fmt.Errorf("$FUNC failed: %w", err)
}
- id: no-console-log-in-production
languages: [javascript, typescript]
severity: WARNING
message: Remove console.log before merging to production
pattern: console.log(...)
paths:
exclude:
- "tests/*"
- "*.test.*"
JWT セキュリティルール
rules:
- id: jwt-none-algorithm
languages: [python]
severity: ERROR
message: JWT decoded without algorithm verification - allows token forgery
patterns:
- pattern: jwt.decode($TOKEN, ..., algorithms=["none"], ...)
metadata:
cwe: ["CWE-347"]
- id: jwt-no-verification
languages: [python]
severity: ERROR
message: JWT decoded with verification disabled
patterns:
- pattern: jwt.decode($TOKEN, ..., options={"verify_signature": False}, ...)
metadata:
cwe: ["CWE-345"]
ルールのテスト
# rules/test-sql-injection.yaml
rules:
- id: sql-injection-format-string
languages: [python]
severity: ERROR
message: SQL injection via format string
pattern: |
cursor.execute(f"...{$VAR}...")
# Test annotation in test file:
# test-sql-injection.py
def bad_query(user_id):
# ruleid: sql-injection-format-string
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
def good_query(user_id):
# ok: sql-injection-format-string
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
# Run rule tests
semgrep --test rules/
# Test specific rule
semgrep --config rules/sql-injection.yaml --test
CI/CD との統合
GitHub Actions
name: Semgrep SAST
on: [pull_request]
jobs:
semgrep:
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
steps:
- uses: actions/checkout@v4
- name: Run Semgrep
run: |
semgrep --config auto \
--config ./custom-rules/ \
--sarif --output results.sarif \
--severity ERROR \
.
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
GitLab CI
semgrep:
stage: test
image: returntocorp/semgrep
script:
- semgrep --config auto --config ./custom-rules/ --json --output semgrep.json .
artifacts:
reports:
sast: semgrep.json
設定ファイル
# .semgrep.yaml
rules:
- id: my-org-rules
# ... rules here
# .semgrepignore
tests/
node_modules/
vendor/
*.min.js
ベストプラクティス
- 自動設定から始め、組織固有のパターンに合わせてカスタムルールを追加します
# ruleid:および# ok:アノテーションを使ってルールをテストします- XSS、SQLi、SSRF などのデータフローの脆弱性には、汚染モードを使用します
- 脆弱性の分類に向けて、CWE や OWASP などのメタデータを含めます
- 可能な場合は、
fixキーを使って修正案を提示します - 誤検知を減らすため、テストファイルを除外します
- 共有リポジトリでルールをバージョン管理します
- ERROR 重大度の検出結果をブロックするチェックとして、CI で実行します
コメント
Markdown 対応