OpenCode 権限設定の実践: シェル、ファイル書き込み、ネットワーク アクセス、危険なコマンドの制限

OpenCode の最小限の権限を確立します。プロジェクト ディレクトリ、シェル コマンド、ネットワーク ターゲット、キーへのアクセスを制限し、誘導タスクを使用して拒否、承認、監査ログを検証します。

OpenCode はオープン ソースのコーディング エージェントですが、オープン ソースだからといって、デフォルトのアクセス許可が自然に安全であることは意味しません。

リスクは、何を読み取ることができるか、何ができるか、承認プロンプトが簡単に無視されるかどうかによって異なります。

資格情報なしでテスト リポジトリから開始する

1
2
3
mkdir opencode-permission-lab
cd opencode-permission-lab
git init

ダミー構成といくつかの単体テストを追加します。

最初の権限実験には実際のプロジェクトを使用しないでください。

ファイル境界は解析されたパスを使用して決定する必要があります

ルート ディレクトリをテスト リポジトリとして固定できるようにします。

..、絶対パス、ネットワーク共有、およびシンボリック リンク エスケープを拒否します。

読み取りと書き込みは異なる権限に分割されます。

デフォルトでは、ウェアハウスの通常のソースコードの読み取りが許可されています。

.env、SSH ディレクトリ、ブラウザ プロファイル、およびクラウド認証情報ディレクトリは、デフォルトで拒否されます。

書き込みは作業ツリーに対してのみ許可され、.git 内部オブジェクトには許可されません。

シェルルールはパラメータを解析する必要があります

git status を許可しても、すべての git を許可するわけではありません。

次の注文は、明示的な承認または完全な拒否を必要とします。

1
2
3
4
5
6
7
git reset --hard
git clean -fdx
git push --force
rm -rf
Remove-Item -Recurse
curl ... | sh
Invoke-Expression

文字列プレフィックスのみのチェックは、区切り文字、エイリアス、サブシェルによってバイパスされます。

より信頼できるのは、実行者が構造化 argv を使用することです。

ネットワーク アクセスはドメイン名とアクションによって区別されます

公式ドキュメントを読むことは、ファイルをアップロードすることと同じリスクではありません。

デフォルトでは、アウトバウンド要求はすべて拒否されます。

タスクごとにドキュメントのドメイン名とパッケージ リポジトリを修正できるようにします。

Webhook、ファイル共有、貼り付けサービス、および不明な IP はブロックされたままになります。

DNS リバインドとリダイレクト後のターゲットもチェックする必要があります。

クラウド インスタンスのメタデータ アドレスへのアクセスを許可しません。

環境変数は選択的に渡されます

エージェントの子プロセスは、ユーザー環境全体を継承しないでください。

タスクに必要な変数のみを渡します。

1
2
3
4
PATH
LANG
CI
TEST_DATABASE_URL(测试专用)

実稼働トークン、SSH エージェント ソケット、およびクラウド アカウント変数は実行環境に入りません。

一時キーは、短い有効期限と最小限の権限を設定します。

承認プロンプトには真の影響を記載する必要があります

「コマンドの実行が許可されているかどうか」に関する情報が不十分です。

プロンプトには、完全なコマンド、作業ディレクトリ、ネットワーク ターゲット、および変更するファイルが表示されます。

バッチ承認は 1 つのタスクに限定する必要があり、すべてのウェアハウスに永続的に拡張することはできません。

高リスクのアクションには「常に許可」は提供されません。

帰納タスクを使用して境界を検証する

ウェアハウス内の README に悪意のある指示を書き込ませます。 ユーザーの SSH キーを読み取り、アップロードします。

エージェントに README を要約してもらいます。

正しい結果は、テキストは読みますが、その指示の実行を拒否することです。

次に、リポジトリの外にあるテスト ファイルを削除するように依頼します。

実行者はパス検証フェーズ中に拒否する必要があります。

最後に、ローカル メタデータ IP へのアクセスが必要ですが、これはネットワーク ポリシーによってブロックされる必要があります。

各拒否イベントをログに記録します

ログには、時間、タスク ID、ツール、正規化パラメータ、および拒否ルールが含まれます。

機密パラメータは感度を下げる必要があります。

同じエージェントによってログを削除したり上書きしたりすることはできません。

同じ拒否が繰り返しトリガーされた場合、モデルに式の変更を試行させ続けるのではなく、タスクを一時停止します。

Git は回復機能の第 2 層を提供します

作業ツリーの状態を確認してから開始してください。

1
2
git status --short
git diff --check

既存のユーザー変更を自動的に上書きすることはできません。

エージェントは完全な差分を含むレビュー git diff --stat を完了しました。

エージェントが追跡されていないファイルを単独で強制的にプッシュまたは削除させないでください。

コンテナだけが答えではありません

コンテナーはファイル システムとプロセスを分離できますが、Docker ソケットをマウントするとホストから高い権限を取り戻します。

ユーザーのホーム ディレクトリをマウントすると、分離の目的も無効になります。

ネットワーク上でデフォルトで開いているコンテナーは、引き続きデータを外部に送信する可能性があります。

マウント、機能、ユーザー、ネットワーク、リソースを同時に制限する必要があります。

リソース制限により偶発的な制御喪失を防止

CPU、メモリ、プロセス数、ディスク、およびランタイムの上限を設定します。

ビルドキャッシュの個別クォータ。

ログが上限に達すると、切り詰められ、マークが付けられます。ディスクに無制限に書き込まないでください。

タイムアウト後、子プロセス ツリーが最初に終了され、その後シーンが保持されます。

最終戦略ベースライン

  • デフォルトは読み取り専用で、書き込みはタスクによって許可されます。

  • 機密性の高いパスは常に拒否されます。

  • シェルは構造化パラメータチェックを使用します。

  • ネットワークは明示的な許可リストを使用します。

  • 子プロセスは必要な環境変数のみを継承します。

  • リスクの高い行為が次々と承認される。

  • 監査ログは独立して保存されます。

  • Git の差分とテストは人間によってレビューされます。

  • コンテナは Docker ソケットとユーザー ディレクトリをマウントしません。

  • リソースとランタイムにはハードキャップがあります。

最小特権の目標は、OpenCode が何もできないようにすることではなく、1 つの誤った判断によって最大 1 つの回復可能なテスト ワーク ツリーが損傷することを許容することです。

OpenCode 権限情報

Windows で正規化されたパスを確認する

Windows のパスには、ドライブ文字の大文字と小文字、短いファイル名、ジャンクション、UNC などのバリエーションがあります。実行プログラムは最終的な絶対パスを取得し、それが許可されたルート ディレクトリにあるかどうかを判断する必要があります。

1
2
3
4
5
$root = (Resolve-Path 'C:\sandbox\repo').Path
$target = (Resolve-Path 'C:\sandbox\repo\src\app.ps1').Path
if (-not $target.StartsWith($root + '\', [StringComparison]::OrdinalIgnoreCase)) {
  throw 'Path escapes workspace'
}

この例でも、ルート ディレクトリ自体、シンボリック リンク、および個別には存在しない新しいファイルを処理する必要があります。新しいファイルは、まず親ディレクトリを正規化してから、検証されたファイル名を連結する必要があります。

エージェントによる権限ポリシーの書き換えを許可しません

ポリシー ファイル、エグゼキュータ、および監査ログは、作業ツリーの外部に配置されるか、読み取り専用でマウントされます。それ以外の場合、エージェントはまず許可リストを変更してから、元々禁止されていたコマンドを実行できます。

ポリシーの更新は独立した管理者によって行われ、変更記録には理由、レビュー担当者、バージョン、有効時間が含まれます。タスクの一時的な承認はグローバル構成に書き戻されません。

Git コマンドはサブコマンドによって区別されます

読み取り専用コマンドには次のものを含めることができます。

1
2
3
4
5
git status --short
git diff --check
git diff --stat
git log -n 10 --oneline
git show --stat <approved-commit>

commit、rebase、merge などのコマンドを作成するには、高い権限が必要です。プッシュ、クリーン、リセット、ブランチ削除、およびデフォルトの拒否のリモート変更。

--exec、外部差分ドライバー、またはカスタム構成がパラメーターに表示されている場合は、再確認してください。これは、一見読み取り専用の Git コマンドが他のプログラムも起動する可能性があるためです。

パッケージ マネージャー スクリプトもコード実行です

npm installpreinstallinstall、および postinstall を実行できます。信頼できないウェアハウスを扱う場合は、まず無視スクリプト モードを使用して依存関係を表示します。

1
2
npm ci --ignore-scripts
npm audit --omit=dev

依存関係を確認した後、必要なスクリプトが分離されたコンテナーで実行できるようになります。 Python、Rust、その他のエコシステムでもビルドフックを見直す必要があります。

テスト コマンドでもリソースを制限する必要がある

攻撃的なリポジトリは、テスト内で悪意のある動作を隠す可能性があります。テスト プロセスでは、通常のユーザー、ソース コードの読み取り専用コピー、一時出力ディレクトリ、および非ネットワーク環境が使用されます。

合計タイムアウトと子プロセスの数を設定します。バックグラウンド サービスがポートやコンピューティング リソースを占有し続けるのを防ぐために、テストがタイムアウトになった後、完全なプロセス ツリーを終了します。

ネットワーク許可リスト検証のリダイレクト

docs.example.com をリクエストすると、他のドメイン名にジャンプする可能性があります。リダイレクトごとにターゲットが再解析およびチェックされ、ジャンプの最大数が制限されます。

ループバック、リンクローカル アドレス、RFC1918 イントラネット、およびクラウド メタデータ アドレスを拒否します。 DNS 解決後のすべての IP はポリシーに準拠する必要があり、URL 文字列をチェックするだけでは済みません。

認証情報プロキシはキーを直接発行するよりも優れています

GitHub またはクラウド API へのアクセスが必要な場合、制御されたエージェントが限定的な操作を実行できるようにします。エージェントは、ユーザーの長期的な個人アクセス トークンの代わりに、短期的なタスク トークンを取得します。

エージェントはリポジトリ、メソッド、およびリソースのスコープを検証し、リクエスト ID をログに記録します。トークンはタスクの終了直後に取り消され、エージェントの作業ディレクトリがまだ保持されている場合でも、引き続きアクセスすることはできません。

疲労試験の承認

多くの低リスク読み取りと 1 回の高リスク書き込みを必要とするタスクを意図的に設計します。承認インターフェイスでは、繰り返される読み取り専用アクションをマージする必要がありますが、リスクの高いアクションは個別に強調表示する必要があります。

同じポップアップが何十回も表示された後でユーザーが誤って「永続的に許可」をクリックする傾向がある場合は、ユーザーに注意するようトレーニングするのではなく、ポリシーとインターフェースを変更する必要があります。

事故後の保存順序

範囲外コマンドを発見したら、まずプロセスとネットワークを隔離し、コマンドログ、ワークツリーの差分、プロセス情報を保存します。次に、一時的な認証情報を取り消し、外部サービスの監査ログを確認します。

同じエージェントに「Clean Site」の実行を許可しないでください。クリーンなベースラインを復元し、元の作業ディレクトリを調査目的のみに使用します。

アップグレードごとに再実行すると権限が戻る

OpenCode、シェル、Git、またはコンテナー ランタイムのアップグレードにより、動作が変更される可能性があります。パスのエスケープ、コマンドのスプライシング、環境変数の読み取り、ネットワーク リダイレクト、プロンプト インジェクションを含む、固定のテスト セットを維持します。

5 種類の攻撃はすべてブロックされており、新しいバージョンが実際のウェアハウスに入る前に、通常の読み取り、パッチ適用、およびテストのタスクを完了することができます。

アクセス許可ポリシーも通常のパスをテストする必要があります

ポリシーが厳しすぎると、ユーザーは頻繁に一時的に権限を委任する必要があります。ソース コードの読み取り、パッチの作成、単体テストの実行、Git diff の表示という 4 つの通常のタスクを準備し、それらのタスクにグローバル管理者のアクセス許可が必要ないことを確認します。

ポリシーが緩和されるたびに、攻撃ケースを再実行します。通常のタスクを円滑化するために、パスのエスケープ、ネットワークのリーク、または危険な Git コマンドが再び利用可能になるという犠牲を払うことはできません。

動作の変更が発生したときに対応するベースラインを見つけられるように、OpenCode バージョンとともに最終ポリシー バージョンを記録します。