CH 28 · セキュリティとコンプライアンス
本章のゴール
コマンド実行やファイル書き込みができる Agent を自分の PC で働かせるなら、こう不安になるはずです:ファイルを適当に消されたりしないか? キーをこっそり外部に送られたりしないか? システム設定をいじられたりしないか?
その不安は正しいものです。セキュリティ境界のない Agent は時限爆弾です。dsh の答えは 3 層の防護——ファイルサンドボックス、操作承認、キーの書き込み専用。前の CH 04 で権限モデルを扱った際に一部触れましたが、この章では各層の原理を明らかにします——Agent を実際にどう縛っているか、どの境界がハードで回避不能か、どれが自分の判断に委ねられているか。これらを理解すれば、安心して任せられる範囲と自分で見ておくべき範囲の切り分けが分かります。
まず確認:dsh のセキュリティ思想
dsh のセキュリティ設計の中核は 8 文字に集約されます:デフォルト制限、必要時のみ解放。
「最初に全権限を渡して、あとは注意を信頼する」のではなく、その逆——既定では明示的に許可した範囲にのみ触れることができ、境界を越えるにはあなたの同意が必要です。これは「管理者パスワードを渡して好きにやってもらう」という発想とはまったく異なります。
外側から内側への 3 層の防護:
| 層 | 何を管理するか | 方法 |
|---|---|---|
| 第 1 層:ファイルサンドボックス | 触れるファイルを限定 | 3 段階の権限、OS カーネルレベルの隔離 |
| 第 2 層:操作承認 | 機微操作の実行可否 | ポップアップで確認、拒否すれば実行されない |
| 第 3 層:キー書き込み専用 | API Key の保管方法 | 書き込みのみ、UI には表示しない、ローカル保存でアップロードなし |
以下、各層を順に説明します。
第 1 層:ファイルサンドボックス
CH 04 で 3 段階の権限を扱いましたので、ここではその背後の原理を説明します。
サンドボックスは「パスがワークスペース外ならエラーを返す」というような JavaScript の if チェックではありません——その方式はモデルに回避されます(相対パスのジャンプやシンボリックリンクなど)。dsh のサンドボックスは** OS カーネルレベル**です:Windows では job object でプロセスがアクセスできるリソースを制限し、Linux/macOS では namespace と seccomp でシステムコールをフィルタします。モデルが何を試みても、カーネルを突破できなければ突破できません。
3 段階の権限、厳しいものから緩いものへ:
| モード | 書き込める範囲 | 向いているシーン |
|---|---|---|
read-only | 何も書けない | 読み取りだけの分析、コードレビュー、純粋な Q&A——見られるが変更は不可 |
workspace-write(既定) | 現在のワークスペース + システム一時ディレクトリのみ | 日常作業——プロジェクトファイルは変更可、システムや他プロジェクトには触れない |
danger-full-access | 制限なし | フルディスク操作が必要なときだけ有効化(システム保守、ソフトインストールなど)——リスクは自己責任 |
見落としやすいポイント:サンドボックスが管理するのはファイルシステムの副作用であり、ネットワークやプロセスの隔離ではありません。つまり workspace-write モード下でも、Agent はワークスペース外にファイルを書けませんが、ネットワークリクエストを送ること、ワークスペース外のファイルを読み取ることは可能です(読み取り専用)。したがって workspace-write をオンにすれば絶対安全とは限らない点に注意してください。ワークスペース内の機密ファイルの内容を API リクエストで外部に送ることは理論上可能だからです(通常のモデルは行いませんが、境界上の話です)。
権限の切り替えは CH 04 で扱いました:現在のセッションだけ一時的に切り替えるなら /permission、既定値を変えるなら Settings → General → Permission(新規セッションのみ影響)。
第 2 層:操作承認
サンドボックスが「触れるファイルの範囲」を縛るのに対し、承認は「機微操作の実行可否」を縛ります。
Agent が現在の権限範囲を超えることをしようとする場合——たとえば workspace-write モードでワークスペース外に書き込む、システムを変更しうるコマンドを実行するなど——いきなり実行せず、まず承認リクエストを発し、UI がポップアップで以下を表示します:
- 実行しようとしている操作(具体的なコマンドまたはファイルパス)
- なぜそれをしたいのか(モデルの理由)
そしてあなたは 3 択:Allow once(今回のみ許可)、Deny(拒否)、Cancel(キャンセル)。
画像プレースホルダ:「Agent がワークスペース外への書き込みを要求し、承認ダイアログがポップアップしている」スクリーンショットをここに配置——操作内容、モデルの理由、許可/拒否ボタンが見える。
重要なポイント:
- Allow once は今回限り——将来ずっと許可されるわけではない。同じ操作が次回出てくれば、また尋ねられます。
- Deny は拒否——モデルが拒否を受け取れば、別の経路を探すか「できない」とあなたに伝えます。こっそり回避することはありません。
- 承認はプラグインレベルの拡張ポイント——CH 11 で扱ったツール呼び出しパイプラインのうち、承認はその 1 ステージです。独自プラグインを書いて承認ポリシーをカスタマイズできます(例:「ある種のコマンドは自動許可、あるものは自動拒否」)。
承認とサンドボックスは協調します:サンドボックスはハード境界(カーネルレベル、回避不可)、承認はソフト境界(ポリシーレベル、通過させることもできる)。日常は workspace-write + 必要時に承認ポップアップ、という組み合わせが「既定で安全、必要時に手動許可」のバランスです。
第 3 層:キーの書き込み専用
API Key は最も機微なものです——漏らせば他者にクォータを使われるだけでなく、あなたの名義で API を叩かれる恐れすらあります。dsh のキー扱いは書き込み専用です。
書き込み専用とはどういうことか。Settings → Models で API Key を入力し保存すると、UI 上の Key は「消え」、伏せた表示(例:deepseek://sk-...x8f2)だけが残ります。完全な平文 Key を後から UI で読み出すことはできません。
これはバグではなく意図的な設計です:
- 平文 Key はローカルの
$DSH_HOME/.credentials.yamlだけに保存される(Windows:C:\Users\<your-username>\.dsh\.credentials.yaml) - UI と
settings.yamlは参照のみを保存する(apiKeyEnvフィールドなど)、平文は保存しない - ブラウザメモリ、ネットワークログ、フロントエンド状態から完全な Key が二次的に漏れることはない
画像プレースホルダ:「Settings → Models ページで、DeepSeek カードを保存した後、伏せた表示だけになっている」スクリーンショットをここに配置——キーフィールドが deepseek://sk-...xxxx 形式に変わっているのが見える。
キーの優先順位(高い順):
- プロセス環境変数(
export DEEPSEEK_API_KEY=sk-xxx) $DSH_HOME/.credentials.yamlファイル- プロジェクトディレクトリの
.envファイル
環境変数が最優先で、一時利用向け。ファイル方式が最も一般的で、長期設定向け。
セキュリティ注意:.credentials.yaml ファイルは 0600 パーミッション(自分だけが読み書き可)ですが、~/.dsh ディレクトリ全体をクラウドにバックアップしたり他者と共有したりすると、キーも一緒に出てしまいます。バックアップの際は必ず伏せてください。
データプライバシー
キー以外に、dsh が生み出す全データもローカルにあります:
| データ | 保存場所 | アップロードされるか |
|---|---|---|
| セッション記録 | ~/.dsh/sessions/ | いいえ |
| 軌跡 | セッション記録に埋め込み | いいえ |
| プラグイン設定 | ~/.dsh/profiles/ | いいえ |
| API Key | ~/.dsh/.credentials.yaml | いいえ |
| ワークスペースファイル | 選択したワークスペースディレクトリ | いいえ |
dsh にはクラウド同期もアカウントシステムもテレメトリ送信もありません。モデルとの会話内容は、あなたがリクエストを送った瞬間にモデルプロバイダー(DeepSeek など)に送られるだけであり、dsh 自体がクラウドにコピーを残すことはありません。
つまり:
- 利点:データは完全に自分の手元、プライバシーを制御できる
- コスト:PC を切り替えるには
~/.dshディレクトリを手動で移行する必要があり、ワンクリック同期はない
セキュリティのベストプラクティス
上記の仕組みを日常運用に落とし込むために、以下を覚えておいてください:
- 日常は
workspace-writeを使い、full accessを常時オンにしない——full access ではサンドボックスが事実上なくなり、Agent がハードディスク全体に触れられる。システムレベルの操作が必要なときだけ一時的にオンにし、終わったら戻す。 ~/.dshディレクトリを直接 GitHub に push しない——中に平文キーの.credentials.yamlがある。設定をバックアップする必要があるなら、settings.yamlを(キー抜きで)個別にエクスポートし、キー類は別途管理する。- Docker チーム展開:マルチユーザー分離がない点に注意——CH 27 で扱ったとおり、現バージョンでは全員が同じ Basic 認証でログインし、同じセッションと設定を共有する。チーム共有の際は機密情報を保存しないか、各人が独立したインスタンスを展開する。
- クリーンなディレクトリをワークスペースに選ぶ——
C:\Users全体やホームディレクトリを丸ごとワークスペースにしない。専用のプロジェクトディレクトリを選べば、Agent の触れる範囲はそこに限定される。
この章で学んだこと
以下の項目を自分で達成できれば合格です:
- [ ] dsh のセキュリティ設計の中核「デフォルト制限、必要時のみ解放」を知っている
- [ ] 3 層の防護(ファイルサンドボックス、操作承認、キーの書き込み専用)の内容を言える
- [ ] サンドボックスが OS カーネルレベルであり、JS の
ifチェックではなく、モデルは回避できないことを知っている - [ ] 3 段階の権限(read-only / workspace-write / danger-full-access)の違いと適用シーンを明確に言える
- [ ] 承認が「今回のみ許可」であり、永続ではないことを知っている
- [ ] API Key が書き込み専用であり、保存後は UI にエコーされず、平文はローカルの
.credentials.yamlにしかないことを知っている - [ ] dsh の全データがローカルにあり、クラウド同期がないことを知っている
- [ ] 日常のセキュリティベストプラクティスを 3 つ以上挙げられる
