次のような場合に使用: ユーザーがGuardianで現在検出できていない問題を検出させたい、セムグレップルール(コード検査パターン)の作成や追加をリクエストしている、またはClaudeが書くコードに対してプロジェクトの規約を適用したい場合 機能: ユーザーと一緒にカスタムセムグレップルール(コード検査パターン)を作成し、それをGuardianにユーザースコープまたはリポジトリスコープで追加します。さらに、ルールが正しく機能することを確認するために、そのルールで検出されるべきコードサンプルを実際に作成して検証します。
write a custom semgrep rule with the user, add it to guardian in either user or repo scope, and prove it fires by writing a file that should trip it. use when someone wants guardian to catch something it currently misses, asks to write or add a semgrep rule, or wants a project convention enforced on the code claude writes.
Guardianは、Claudeが書いたり編集したりするすべてのファイルをスキャンします。カスタムルールを作成すると、デプロイメント(本番環境)のルールセットでは検出できない問題を捉えられます。たとえば、プロジェクト独自の決まり事、廃止予定の社内API、チームが何度も引っかかるバグの原因になりやすいコードなどです。
ルールは2つの場所に保存され、スキャンのたびに両方が読み込まれます:
~/.semgrep/guardian-rules/ — ユーザー範囲。あなたがどのリポジトリ(コード倉庫)を開いても適用されます<repo root>/.semgrep/guardian-rules/ — リポジトリ範囲。コードと一緒に保存されるため、リポジトリをクローン(複製)した全員がそのルールを使えますこれらのディレクトリに直接書き込むのではなく、add_developer_semgrep_ruleを使ってルールを追加してください。このツールは自動的に保存先を判断し、既存のルールを上書きしません。また、ルール自体の検査やデプロイメント制限の確認はスキャン時に行われるため、その結果は後のステップ5で分かります。
1つのファイルに1つのルールか、複数ルールのリスト(rules:)を入れられます。 パースに失敗したファイル(読み込みエラー)は丸ごと拒否されるため、1つのファイルに複数ルールを入れると、それらは一緒に送信されるか、まったく送信されないかのどちらかになります。このスキルは1ファイルにつき1ルールを書き込むため、問題が1つのルールに限定されます。
まずlist_developer_semgrep_rulesを実行してください。両方のディレクトリ、既存のルールファイル、それらが送信されているかどうか、およびデプロイメントの上限を報告します。
guardian.developer_rules_enabledを有効にするよう依頼するよう伝えてください。loginツールを使用)してから再試行するよう依頼します。既存のルールIDを記録します。新しいルールのIDはこれらと重複しない必要があります。
マッチするべきコードを尋ねてください。また、もしあれば、似ているがマッチするべきでないコードも聞いてください。必要な情報は:プログラミング言語、悪いケースが悪い理由(感覚ではなくコードの形)、近くにあるどのコードは通すべきか、です。両方のコード片を記録してください。ステップ5で検証用の例として使います。
rules:
- id: no-direct-requests-get
message: use the retrying client in lib/http.py, not requests.get directly.
severity: WARNING
languages: [python]
patterns:
- pattern: requests.get(...)
- pattern-not-inside: |
def _retrying_get(...):
...
patternは1つのコードパターンにマッチします。...は任意の並び(引数、文、要素など)を表し、$xはメタ変数(同じ名前が2回出てくれば、同じコード構造を意味します)です。patterns:は「かつ」、pattern-either:は「または」の意味です。誤検出を減らすにはpattern-not、pattern-not-inside、metavariable-regexを使います。languages:はpython、javascript、typescript、go、java、ruby、generic、およびSemgrepの完全なリストから選べます。severity:はERROR、WARNING、またはINFOです。idは新しく、かつ具体的である必要があります。httpではなくno-requests-get-in-handlersのような名前にしてください。別のローカルルールと衝突した場合、後のファイルが丸ごと除外されます。デプロイメントのルールセットと衝突した場合、あなたのルールが除外されます。Guardianがこれらのルールを実行する方法に関する2つの重要な点があり、ルール設計に影響します:
askuserquestionを使ってください。選択肢はルールの対象です:
<repo>/.semgrep/guardian-rules/に置かれ、コミット後チーム全体で共有されます。~/.semgrep/guardian-rules/に置かれ、他の人には見えません。プロジェクト固有のことを名前に付けたルールはrepoをデフォルトに、この人のコード書き方の好みについてのルールはuserをデフォルトにしてください。
add_developer_semgrep_ruleを呼び出します。引数はルール本体、選んだscope(範囲)、保存するファイル名のnameです。ルールのIDをファイル名に使ってください。例:no-eval.yaml。このツールはあなたが与えたものをそのまま書き込み、ファイル名か保存先だけを拒否できます:
"x" must be a file name rather than a path」(パスではなくファイル名にしてください)— ファイル名だけを渡してください。<path> already exists; pass a different name」(そのファイルは既に存在します)— そのファイルは誰かが作業中のルールです。別の名前を選ぶか、ユーザーが置き換える意図ならそのファイルを編集してください。repo scope needs a git repository, and this is not one」(リポジトリ範囲にはGitリポジトリが必要です)— ユーザー範囲を提案してください。追加が成功しても、ルールが実際に使えるかどうかについては何も保証しません。ツールはファイルを先に書き込み、何も確認しないためです。そのため、即座にlist_developer_semgrep_rulesを再度実行して、新しいファイルがリストに入っているか確認してください:
idがないルールです。すべてのスキャンから無言で除外されるため、今すぐ修正してください。検証用の例は実行しなくて大丈夫です。n developer rules on disk, over the limit of m」(ディスク上に n個のルール、上限 m個を超えています)— デプロイメントの上限を超えました。上限超過は追加ルールが無視される意味ではなく、すべてのルールが送信されず、Guardianはカウントが上限を下回るまで書き込みをブロックします。追加したばかりのファイルを、このツールが返したパスから削除し、再度リストして、ルールが送信されていることを確認してください。その後、ユーザーに伝えてください:このルールを保つには、別のルールを廃止(remove-guardian-developer-semgrep-ruleスキルを使用)し、改めて追加してください。developer rules are n bytes, over the m byte limit」(ルールの総容量がm バイト制限を超えています)— 同じことですが、ルール数ではなく容量で計算され、同じようにブロックします。新しいファイルを上記と同じ手順で削除し、その後ルールを小さく(messageを短く、metadataを減らし、pattern-not句を減らす)して再度追加するか、別のルールを廃止してから追加することを提案してください。すべてのルールが送信されていて、あなたのファイルがエラーなしでリストに含まれるまで、検証用の例を書かないでください。
Guardianはコードの形のみチェックし、Semgrepがルールを受け入れるかどうかは検査しません。スキャナーが拒否するルールは、ブロックとしてではなく、スキャナーのパースエラーを含む失敗スキャンとして、次のステップで表示されます。これが、YAMLを修正してもう一度試すシグナルです。
実際に使われる方法でテストしてください。ルールにマッチするコードを書きます。ユーザーに先に、この書き込みは意図的にブロックされるので、ブロックは失敗ではなく成功だと伝えてください。
guardian-rule-check.py。新しいファイルにwriteを使ってください。編集は編集が導入した検出結果のみを報告し、新しいファイルには比較対象がありません。本物のソースファイル拡張子(.pyなど)を使ってください。Markdownはスキャンされず、作業ディレクトリの外のファイルもスキャンされません。messageでブロックします。このブロックがルールの動作です。代わりにスキャンが失敗したら、スキャナーがそのルールを受け入れていません。スキャナーのエラーを読み、ディレクトリ内のファイルを修正してから検証用の例を再度書き込んでください。何もマッチしなかった場合、そのルールは既にディスク上にあります。範囲のディレクトリ内でインプレース(その場で)編集し、検証用の例を再度書き込んでください。すべてのスキャンがルールを再読込みするため、再起動は不要です。順番に確認してください:list_developer_semgrep_rulesがルール送信を報告しているか、languages:が検証用の例のファイル拡張子に一致しているか、パターンが特異すぎないか(pattern-not句を削除して、マッチするルールから再度絞り込んでください)。
list_developer_semgrep_rulesをもう一度実行し、ユーザーに以下を伝えてください:
~/.semgrep/guardian-rules/と<repo>/.semgrep/guardian-rules/の2つのディレクトリにある普通のYAMLファイルなので、ツールを使わずに直接編集・削除できることrules:リストで1エントリ入れるか、1つのベアルール(リストなし)を入れられます。どちらでも動作します。同じファイルに2番目のルール、または---の後に2番目のYAMLドキュメントがあると、ファイル全体が使えなくなります。list_developer_semgrep_rulesはこの上限と、ディスク上のルールのうちいくつが上限以下に収まるかを報告します。messageとmetadataには秘密情報を含めないでください。guardian scans every file claude writes or edits. a custom rule makes it catch something the deployment's ruleset does not — a project convention, a deprecated internal api, a footgun this team keeps hitting.
rules live in two places, both read on every scan:
~/.semgrep/guardian-rules/ — user scope, follows the user into every repository<repo root>/.semgrep/guardian-rules/ — repo scope, follows the code, so everyone who clones it gets the ruleadd rules with add_developer_semgrep_rule rather than writing into those
directories by hand: it resolves the scope's directory and will not write over
a rule already there. it does not check the rule itself or count it against the
deployment's limit — that happens when a scan reads the rules, and step 5 is
how you find out.
a file can hold one rule or a rules: list. a file that fails to parse is
rejected whole, so rules kept in one file are sent together or not at all. this
skill writes one rule per file, which keeps that blast radius at one rule.
call list_developer_semgrep_rules before anything else. it reports both
directories, the rule files already there, whether they are being sent, and the
deployment's limit.
guardian.developer_rules_enabled.login tool), then retry.note the existing rule ids; yours has to be new.
ask for code that should match, and if they have it, code that looks similar and should not. you need the language, what makes the bad case bad as a code shape rather than a feeling, and what nearby code must keep passing. write both snippets down — step 5 uses them as fixtures.
rules:
- id: no-direct-requests-get
message: use the retrying client in lib/http.py, not requests.get directly.
severity: WARNING
languages: [python]
patterns:
- pattern: requests.get(...)
- pattern-not-inside: |
def _retrying_get(...):
...
pattern matches one shape. ... stands for any sequence (arguments,
statements, elements), and $x is a metavariable — the same name twice means
the same code twice.patterns: is and, pattern-either: is or. cut false positives with
pattern-not, pattern-not-inside, metavariable-regex.languages: takes python, javascript, typescript, go, java, ruby,
generic, and the rest of semgrep's list. severity: is ERROR, WARNING, or INFO.id must be new and specific — no-requests-get-in-handlers, not http.
against another local rule, the later file is dropped whole; against the
deployment's ruleset, your rule is the one dropped.two things about how guardian runs these, which should shape the rule:
use askuserquestion. the choice is who the rule is for:
<repo>/.semgrep/guardian-rules/ and is shared with the team once committed.~/.semgrep/guardian-rules/, and nobody else sees it.default to repo when the rule names anything specific to the project, user when it is about how this person likes to write code.
call add_developer_semgrep_rule with the rule text, the chosen scope, and a
name to write it as — name the file after the rule's id, e.g. no-eval.yaml.
the tool writes what you give it; it can only refuse the name or the place:
"x" must be a file name rather than a path — pass a bare name.<path> already exists; pass a different name — that file is somebody's
working rule. pick another name, or edit that file if the user meant to
replace it.repo scope needs a git repository, and this is not one — offer user scope.the add succeeding says nothing about whether the rule is usable or fits: the
tool writes the file first and checks nothing. so call
list_developer_semgrep_rules straight away, before any other write, and find
the new file in it:
id. it is left out of
every scan without a word, so fix it in place now; the fixture below would
just go through.n developer rules on disk, over the limit of m — the deployment's cap, and
your file is what crossed it. going over does not mean the extra rule is
ignored: no rules are sent, and guardian blocks writes until the count is
back under. delete the file you just added, at the path the add returned,
and list again to confirm rules are being sent. then tell the user: to keep
this rule, retire another (the remove-guardian-developer-semgrep-rule
skill) and add it again.developer rules are n bytes, over the m byte limit — the same thing by
weight rather than by count, and it blocks the same way. delete the new file
as above, then offer to shrink the rule (a shorter message, less
metadata, fewer pattern-not clauses) and add it again, or retire another.do not write the fixture until the listing shows every rule being sent and your file among them without an error.
guardian checks only the shape, not whether semgrep will accept the rule. a rule the scanner rejects shows up in the next step as a failed scan carrying the scanner's parse error rather than as a block. that is the signal to fix the yaml and try again.
now test it the way it will actually be used, by writing code that trips it. tell the user first that the write is meant to be blocked, so the block does not read as a failure.
guardian-rule-check.py. use write on a new file: an edit only reports
findings the edit introduced, and a new file has no baseline to subtract.
give it a real source extension; markdown is never scanned, and files outside
the working directory are not either.message. that
block is the rule working. a scan that fails instead means the scanner
would not take the rule — read its error, fix the file in place, and write
the fixture again.if nothing fires, the rule is already on disk — edit it in place in the scope's
directory and write the fixture again; every scan re-reads the rules, so nothing
needs restarting. work through, in order: does list_developer_semgrep_rules
say the rules are being sent, does languages: match the fixture's extension,
and is the pattern too specific (drop the pattern-not clauses and narrow again
from a rule that fires).
run list_developer_semgrep_rules once more and tell the user:
rules: list with one entry or a single bare
rule. either works; a second rule in the same file, or a second yaml document
after ---, makes the whole file unusable.list_developer_semgrep_rules reports the cap and how many of the rules on
disk fit under it.message and metadata all the same.原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。