ルール設定ファイルの場所
CC Safety Net は、2 つのスコープから rulebook を読み込んでマージします。- ユーザースコープ:
~/.cc-safety-net/rules/rule.json(rule init --globalで作成)。すべてのプロジェクトに適用したい個人の既定値に使います。 - プロジェクトスコープ:プロジェクトルートの
.cc-safety-net/rules/rule.json。バージョン管理にコミットできる、チームやプロジェクト固有のルールに使います。
project-rules のような単純な名前で参照します。GitHub 上の rulebook は owner/repo#ref/<rulebook-name> の形式で参照し、そのリポジトリ内の .cc-safety-net/rules/<rulebook-name>/rulebook.json を指します。rule add と rule update は、そのファイルを同じ相対パスで自分のスコープに取り込みます。有効な rulebook は、どれも自分の設定ディレクトリ内のファイルです。
スコープをマージするときの挙動
- 両スコープの rulebook を、ユーザースコープを先にして結合します。
- 有効な rulebook の名前が重複した場合は、先に読み込んだ側が優先されます。 ユーザースコープを先に読み込むため、同名のプロジェクト rulebook は読み込まれません。ルールの一部だけが隠れるわけではありません。この衝突は警告として報告され、ランタイムは
degraded状態になります。どちらかの名前を、rulebook ファイルとそれを参照するrule.jsonの両方で変更してください。この衝突は致命的エラーではなく、先に読み込んだ側を採用して解決されます。そのため、もう一方のスコープが同じ名前をすでに使っていても、設定元の追加や更新は成功します。 - 各スコープの
overridesは、そのスコープ自身のルールにのみ適用されます。 ユーザースコープのルールを指定したプロジェクト側の override は警告とともに無視され、そのルールはユーザー設定の状態を保ちます。プロジェクトの設定から、ユーザーのルールを無効にしたり書き換えたりすることはできません。 - どの既知のルールにも一致しない override のキーは、警告とともに無視されます。他の override とルールは設定どおりのまま有効です。
transparent_wrappersは、両スコープの内容を統合します。
rulebook の設定元を管理する
rulebook の設定元は、rule.json の rules 配列のエントリで指定します。指定できるのは次の 2 種類です。
- ローカル:
project-rulesのような単純な名前です。rulebook は.cc-safety-net/rules/project-rules/rulebook.json(プロジェクト)または~/.cc-safety-net/rules/project-rules/rulebook.json(ユーザー)に置きます。ローカルの設定元は、設定ディレクトリの外に出てはいけません。 - GitHub:
owner/repo#ref/<rulebook-name>の形式で、そのリポジトリと ref にある.cc-safety-net/rules/<rulebook-name>/rulebook.jsonを指します。rule addとrule updateは、取得したバイト列をそのまま自分のスコープの.cc-safety-net/rules/<rulebook-name>/rulebook.jsonに取り込むため、ローカルの rulebook とまったく同じように読み込まれます。
rule.json を直接編集するのではなく rule コマンドを使ってください。
--global(-g)を付けると、プロジェクトスコープではなくユーザースコープを対象に実行します。例外は rule list で、常に両方のスコープを読み、--global は受け付けません。rule の各サブコマンドとそのオプション、終了時の挙動は、CLI コマンドを参照してください。
リポジトリから rulebook をインストールする
rule add は、正式な形式である owner/repo#ref/<rulebook-name> に加えて、リポジトリだけを指定する owner/repo も受け付けます。リポジトリだけを指定した場合は、そのリポジトリが .cc-safety-net/rules/ 配下で公開しているすべての rulebook を追加します。対象を絞るオプションが 2 つあり、どちらも owner/repo 形式の rule add でのみ使えます。
--only <rulebook...>には rulebook 名を 1 つ以上指定します。指定した順序はそのまま保たれます。--ref <ref>では、リポジトリの既定ブランチではなくブランチ・タグ・コミットを指定します。ref には/を含められるので、--ref feature/rulebook-v2のような指定も可能です。
rule.json に保存されるのは正式な形式 owner/repo#ref/<rulebook-name> で、解決後のコミットではなく指定した ref がそのまま残ります。つまり、この ref は動く参照のままです。解決されたコミットは保存されず、実行結果として Vendored at 1a2b3c4. のように表示されるだけです。rulebook ファイルは書き込まれますが、コミットを固定するロックファイルはありません。
rule update は、選択した設定元をすべて解決し直します。ブランチやタグの ref は現在の位置に追従し、取り込み済みのファイルはそこから書き直されます。設定元ごとの処理は独立しています。取得や検証に失敗した設定元は取り込み済みのファイルを保ったまま Failed to update <spec>: <message> として報告され、他の設定元は更新されます。例外はリソース上限の超過で、この場合は実行全体が中止されます。
リソース制限
rules 配列に指定できる設定元は、スコープごとに最大 64 件です。これを超えるエントリを持つ rule.json は、Rule config exceeds CC Safety Net's safe source limit. という 1 件のエラーで検証に失敗します。件数超過の配列はエントリごとに個別報告されず、他の無効な rule.json と同じように、そのスコープの設定全体が実行中のスナップショットから破棄されます。
GitHub からの取得は、決められた上限の中で動作します。rule add と rule update が同時に処理する設定元は最大 4 件、1 回の実行で発行する GitHub リクエストは最大 131 件、すべての設定元を合わせて読み取るレスポンスは最大 64 MiB です。いずれかの上限を超えると、Rule synchronization exceeds CC Safety Net's safe resource limits. を表示して処理を中止します。このとき失敗するのは上限を超えた設定元だけではなく、その実行に含まれるすべての設定元です。
rulebook ファイル自体にも上限があり、スキーマより先に確認します。いずれかを超えた rulebook は、フィールドごとの内訳なしに Rulebook exceeds CC Safety Net's safe validation limits. の 1 行だけで拒否されます。
上限を満たしたうえでスキーマ検証に失敗した場合、報告するエラーは最大 64 件で、その後に
Additional rulebook validation errors were omitted. が続きます。
rulebook はライブファイル
ロックファイルもダイジェストもキャッシュもありません。どの設定元も<config-dir>/<rulebook-name>/rulebook.json から読み込まれ、ランタイムはツール呼び出しのたびにそのファイルを読みます。ローカルの rulebook はその場所で直接編集し、リモートの rulebook は rule add と rule update がその場所に取り込みます。保存した編集は次のコマンドから有効になり、あとから反映させたり再構築したりする手順はありません。
rulebook.json が見つからない、読み取れない、または無効な設定元は無効になります。その設定元はルールを提供しませんが、他のすべての設定元と組み込み保護は適用され続け、通常のコマンドも動き続けます。ランタイムはこの状態を degraded として報告します。rule.json が読み取れない、または無効な場合は、そのスコープのすべての設定元が無効になります。GitHub の設定元がまだ取り込まれていない場合は、npx -y cc-safety-net rule update を実行してください。
状態遷移の全体像、診断メッセージの正確な文言、修復手順については、設定の復旧を参照してください。
rule sync は非推奨
rule sync はもう何も同期しません。以前のバージョンが残した rule.lock と cache ディレクトリを、オフラインで移行するだけです。記録されたダイジェストと一致するキャッシュ済みの rulebook を、その設定元が読み込むライブのパスへ取り込み、両方を削除します。実行するたびに、次の 1 行から始まります。
doctor が info 重大度の finding Rulebook lock and cache leftovers detected として報告します。移行が出力するメッセージの全体と、実行を拒否する条件は rule sync を参照してください。
transparent wrapper
チームがrtk のようなラッパー経由でコマンドを実行している場合、既定の解析はラッパーだけを見ます。その先で実行されるコマンドは検査しません。transparent_wrappers にラッパーを登録すると、CC Safety Net はその先にある保護対象の子コマンドも解析します。rtk git reset --hard や rtk docker system prune にも、ラッパーなしのコマンドと同じ組み込み解析とカスタムルールが適用されます。
ラッパーの設定は rule wrapper サブコマンドで行ってください。rule.json を直接編集する必要はありません。
- 組み込みの既定値はありません。 意図的に信頼するラッパーだけを設定してください。
- ラッパー名は
^[a-zA-Z][a-zA-Z0-9_-]*$に一致し、ファイル内で一意である必要があります。 - 予約済みのコマンドはラッパーにできません。 対象は
git、busybox、解析対象の組み込みコマンドであるrm、find、xargs、parallel、すべてのシェルラッパー、すべてのインタープリター、および awk 系のインタープリターです。 - 透過処理では、ラッパーのフラグと
VAR=value形式の代入を読み飛ばした後の最初の保護対象になりうる子コマンド、または明示的な--の直後のトークンを探します。子コマンド自体が保護対象になりえない場合、透過処理は行いません。 - ここに登録されていないラッパーや、子コマンドをそのまま exec せずに書き換えたり隠したりするラッパーは、透過処理の対象になりません。そうしたコマンドを拾える可能性があるのは、トップレベルの危険な文字列に対するフォールバックスキャンだけです。
最初のカスタムルールを作る
まず、プロジェクト用のルール設定のひな形を作成します。.cc-safety-net/rules/rule.json が作成されます。この時点では、rulebook の設定元は設定されていません。
--example を付けると、サンプルの rulebook も .cc-safety-net/rules/example-rules/rulebook.json に書き出されます(この時点ではまだ有効になりません)。書き出されるのはそのファイルがまだ存在しない場合だけで、rule init はそれを設定元として登録しないため、有効にするには自分で設定元として追加する必要があります。
.cc-safety-net/rules/project-rules/rulebook.json を作成し、npx -y cc-safety-net rule add project-rules で登録します。すると rule.json は次のようになります。
git add -A、git add --all、git add . が指定したメッセージとともにブロックされます。その前にファイルを確認したい場合は、次を実行します。
rule.json のスキーマ
最上位の rule.json は、どの rulebook を有効にするかを選び、override を適用し、transparent wrapper を宣言します。安全レベル、組み込み保護、パスの許可と拒否、監査ログの保持期間を設定する policy.json とは別のファイルです。policy.json についてはポリシーを参照してください。
integer
必須
スキーマのバージョン。
1 である必要があります。array
rulebook の設定元を表す文字列のリストです。既定値は空の配列です。設定元の名前はファイル内で一意である必要があり、指定できるのは最大 64 件です。リソース制限を参照してください。
object
<rulebook-name>/<rule-name> をキーとするルールの上書き設定です。値には、ルールを無効にする "off" か、ルールのブロックメッセージを差し替えるオブジェクトを指定します。オブジェクト形式では reason が必須で、intent は任意です。intent を省略した場合、ルール本来の intent は変わりません。array
保護対象の子コマンドをそのまま実行するコマンド名です。解析はこれらを透過して子コマンドを見ます。既定値は空の配列です。各項目は一意で、予約済みコマンドであってはいけません。transparent wrapperを参照してください。
エディターでの rule.json 補完
CC Safety Net は、ランタイムと同じ定義から生成した rule.json の JSON Schema を公開しています。エディターにこのスキーマを指定すると、補完と検証を利用できます。
rule.json のフィールド(version、rules、overrides、transparent_wrappers)だけです。rule verify を実行すると、この $schema の指定がない有効なルール設定に対して、指定が自動的に追加されます。policy.json に対応する公開スキーマはありません。
rulebook のスキーマ
各 rulebook は、独立したrulebook.json ファイルです。
integer
必須
rulebook のスキーマバージョン。
1 または 2 である必要があります。それ以外の値は rulebook_version must be 1 or 2 として検証に失敗します。バージョン 2 のルールを参照してください。string
必須
rulebook の名前。ローカルのディレクトリ名、または GitHub の設定元の名前と一致している必要があります。
string
必須
rulebook のバージョン文字列。
string
rulebook の説明文。
string
rulebook の作成者。
array
必須
この rulebook でルールを定義できるコマンド。
array
rulebook のフィクスチャ(任意)です。フィクスチャのスキーマを参照してください。バージョン 1 のフィクスチャは形式だけを検証します。バージョン 2 のフィクスチャは、rulebook 自身のルールに対して実際に評価されます。
ルールのスキーマ
以下のフィールドはrulebook_version 1 のルールを定義します。バージョン 2 では subcommand と block_args が match オブジェクトに置き換わります。バージョン 2 のルールを参照してください。
string
必須
rulebook 内で一意である必要があります。先頭は英字で、以降は英数字、ハイフン、アンダースコアが使えます。最大 64 文字です。
string
必須
照合するベースコマンド。
allowed_commands に記載されている必要があります。string
照合するサブコマンド(
add、install など)。省略した場合は、すべてのサブコマンドに一致します。array
必須
ブロックのきっかけとなる引数です。1 つ以上必要です。
string
必須
ブロック時に表示するメッセージ。最大 256 文字です。
string
ブロックメッセージの末尾に付き、エージェントが次に取る行動の指針になります。
hard_stop、use_alternative、scope_down、manual_only、stop_and_explain のいずれかを指定します。既定値は manual_only です。バージョン 2 のルール
"rulebook_version": 2 を指定すると、サブコマンドと引数の集合ではなく、コマンドパスの完全一致で照合できます。gcloud compute の下で delete をブロックするバージョン 1 のルールは、コマンドのどこにそのトークンがあっても照合するため、gcloud compute instances create delete もブロックします。コマンドパスに ["compute", "instances", "delete"] を指定したバージョン 2 のルールなら、これはブロックしません。
バージョン 1 の rulebook は、フィールドも照合の挙動も、形式のみを検証するフィクスチャも、これまでどおりです。各 rulebook は、自身が宣言したバージョンで検証されます。
バージョン 2 のルールは、バージョン 1 の name、command、reason、intent をそのまま引き継ぎ、subcommand と block_args を match オブジェクトに置き換えます。
array
必須
コマンドの後に、この順序で続く必要があるコマンドワード。空でない文字列からなる、空でない配列です。
array
引数の中に、ここに挙げたトークンが少なくとも 1 つそのまま現れる必要があります。要素は空でない文字列で、重複は許されません。配列自体も空にはできません。
array
引数の中にここに挙げたトークンがそのまま現れると、照合しません。要素は空でない文字列で、重複は許されません。配列自体も空にはできません。
subcommand や block_args が残っているルールは、rules[0].subcommand: not supported in rulebook_version 2 および rules[0].block_args: not supported in rulebook_version 2 として検証に失敗します。
バージョン 2 の照合
- コマンド:バージョン 1 と同じく、小文字のベース名に正規化されます。
- コマンドパス:CC Safety Net は引数をたどり、認識済みの値を取るグローバルオプションを、その値ごと読み飛ばします。そこで現れるコマンドワードが、
command_pathと順序も含めて完全に一致する必要があります。パスより後ろの引数は、パスの照合に影響しません。 - グローバルオプションの一覧:値を取るグローバルオプションが組み込まれているのは
aws、gcloud、azの 3 つだけです。Terraform に一覧は不要です。唯一のグローバルオプションである-chdir=DIRは=で連結されているため、1 つのトークンとして読み飛ばされます。 - 未知のオプション:そのコマンドの一覧にない
-で始まるトークンは、値を消費せずに読み飛ばされます。そのため、一覧にない値を取るオプションを値と分けて書くと(--newflag value)、ルールは照合しません。この不一致は意図的なものです。CC Safety Net は、認識できないオプションではブロックせずに fail open します。rulebook の作成者は、これを既知の穴として rulebook 内に明記してください。 - 短いオプションは展開しません:
-Apは-Apのままです。"-destroy"と"--destroy"のように、拾いたい表記をすべて列挙してください。 - リテラルかつ大文字小文字を区別:正規表現・glob・部分一致には対応しません。
- 最初に一致したルールが優先:ルールは順に評価され、最初に一致したルールがブロックを生成します。
- リリースチャネルには専用のルールが必要:
gcloud beta compute instances deleteは、["compute", "instances", "delete"]というcommand_pathには一致しません。["beta", "compute", "instances", "delete"]を指定した 2 つ目のルールを書いてください。
フィクスチャのスキーマ
フィクスチャは、意図した動作を記録するためのものです。CC Safety Net はコマンドをパースして rulebook のルールに掛けるだけで、実行することはありません。string
必須
フィクスチャとなるシェルコマンド。
string
必須
blocked または allowed のいずれか。string
そのコマンドをブロックすると想定されるルール。
blocked のフィクスチャでは必須です。rule add や rule update が設定元を取得したときと、rule verify が rulebook のディレクトリを読んだときに、rulebook 自身のルールに対して評価されます。blocked のフィクスチャは、指定したルールが最初に一致した場合にだけ通ります。allowed のフィクスチャは、どのルールも一致しなかった場合にだけ通ります。フィクスチャが失敗した設定元はファイルが書き込まれる前に拒否されるため、自身のフィクスチャと矛盾する rulebook が有効になることはありません。rulebook の読み込み時に、フィクスチャが再評価されることはありません。
失敗は、tests 内のインデックスとともに報告されます。
rule verify は、example-rules/rulebook.json: tests[0]: ... のように rulebook ファイル名を先頭に付けて表示します。
照合の挙動
以下のサブコマンド・引数・オプションの規則は、rulebook_version 1 のルールについての説明です。バージョン 2 のルールの照合はバージョン 2 の照合を参照してください。コマンドの正規化、評価順序、transparent wrapper は、どちらのバージョンにも当てはまります。
- コマンドの正規化:コマンドは照合前にベース名へ変換されます。
/usr/local/bin/npmは"command": "npm"のルールに一致します。 - サブコマンドの判定:サブコマンドは、コマンドの後にある最初のオプションでない引数です。
git --no-pager add -Aのサブコマンドはaddです。 - 引数の照合:
block_argsの引数はリテラルとして照合されます。正規表現や glob には対応していません。 - 短いオプションの展開:
-Apのようにまとめて書かれた短いフラグは、照合前に分解されます。-Apは-Aと-pとして扱われます。 - 長いオプションの照合:長いオプションは文字列の完全一致で照合します。
--all-filesは--allに一致しません。 - いずれか 1 つでも一致すればブロック:
block_argsのうち 1 つでもコマンドに含まれていれば、そのコマンドはブロックされます。 - 追加のみ可能:カスタムルールで追加できるのは新しい制限だけです。組み込みの保護を迂回することはできません。
既知の制限:
-Cfoo は -C foo ではなく -C -f -o -o として扱われます。そのため -f をブロックしていると、オプションに続けて書かれた値によって誤検知が起きることがあります。例
npm のグローバルインストールをブロックする
npm のグローバルインストールをブロックする
エージェントがパッケージをグローバルにインストールできないようにします。
危険な docker コマンドをブロックする
危険な docker コマンドをブロックする
docker system prune をブロックします。1 つの rulebook に複数のルールを定義する
1 つの rulebook に複数のルールを定義する
ブロックメッセージの形式
ブロックメッセージ全体の構成は、ブロック結果の形式で説明しています。カスタムルールの場合は rulebook 名とルール名がプレフィックスとして付くため、どの rulebook によるブロックかがわかります。<rulebook-name>/<rule-name> です。これは、rule.json の overrides でルールを無効化("off")したり理由を差し替えたりするときに使うキーでもあります。
rulebook を検証する
rulebook を作成または編集したら、次のコマンドで検証します。rule verify は、両方のスコープの rule.json を検査し、設定された各設定元をガードと同じ方法で読み込み、カレントリポジトリの .cc-safety-net/rules/ 配下にあるすべての rulebook ディレクトリを、バージョン 2 のフィクスチャも含めて検証します。リモートのコンテンツを取得することはありません。
旧形式の設定を移行する
旧形式のインライン設定ファイル(.safety-net.json と ~/.cc-safety-net/config.json)は、実行時に読み込まれなくなりました。
旧形式のルールが元の場所から強制されることはなく、逆に作業をブロックすることもありません。ランタイムは旧形式のファイルをまったく参照しないため、ガードの実行時には何も現れません。残っている旧形式ファイルについて警告するのは
npx -y cc-safety-net rule verify です。アップグレード後に実行してください。
rule migrate が自動的に作成する rulebook ベースの構成です:
カスタムルールの設定が無効な場合
読み込みに失敗したカスタムルールの設定は、破棄され、強制されません。その設定自体が拒否に変わることもありません。通常のコマンドは動き続けます。有効な他の設定元と組み込みの保護も引き続き適用されます。ランタイムは、この状態をdegraded として報告します。
設定元が破棄されると、それまでの拒否がなくなります。拒否が増えるわけではないため、この失敗だけで作業が止まることはありません。日常の確認には npx cc-safety-net status を使ってください。失敗とフォールバックの対応表、診断メッセージ、表示箇所、修復手順は、設定の復旧を参照してください。