セキュリティ
セキュリティ
SSH-Frontièreはセキュリティコンポーネントです。その目的は、受信SSH接続が実行できる内容を制限することです。このページでは、セキュリティモデル、実装された内容、保証されない事項を文書化しています。
セキュリティモデル
基本原則:デフォルト拒否
明示的に設定されていないものは実行されません。コマンドがTOMLホワイトリストに含まれていなければ拒否されます。許容モードもシェルへのフォールバックもありません。
多層防御の3つの層
| 層 | メカニズム | 防御内容 |
|---|---|---|
| 1 | authorized_keysのcommand= + restrict | アクセスレベルを強制、フォワーディング/PTYをブロック |
| 2 | SSH-Frontière(ログインシェル) | TOMLホワイトリストに対してコマンドを検証 |
| 3 | sudoersのsudoホワイトリスト | 特権システムコマンドを制限 |
攻撃者がSSH鍵(第1層)を侵害しても、TOMLホワイトリスト(第2層)で許可されたコマンドしか実行できません。第2層を迂回しても、sudoers(第3層)で許可されたコマンドに対してのみ権限昇格が可能です。
文法パーサーであり、ブラックリストではない
SSH-Frontièreはシェルではありません。セキュリティは文字フィルタリング(|、;、&のブラックリストなし)ではなく、文法パーサーに依存しています。
期待される文法はドメイン アクション [key=value ...]です。この構造に一致しないものはすべて拒否されます。引用符内の特殊文字は引数の内容であり、構文ではありません — これらは有効です。
std::process::Commandは中間シェルを経由せずに直接実行します。コマンドインジェクションは構造的に不可能です。
AIエージェントに対する決定論性
この動作は決定論的です:特定のコマンドは、コンテキストに関係なく常に同じ検証結果を生成します。これは、AIエージェントと連携する際に不可欠な特性です。AIエージェントの本質はまさに非決定論であり — モデルにバイアスがかかったり、エージェントの生成チェーンが破損し、追加情報の抽出や秘密の流出を目的としてシェルを標的にする可能性があります。SSH-Frontièreを使用すれば、侵害されたエージェントがホワイトリストを迂回すること、シェルにコマンドをインジェクトすること、設定されていないリソースにアクセスすることは構造的に不可能です。
実装済みの機能
Rust言語
SSH-FrontièreはRustで書かれており、システムプログラムにおける最も一般的な脆弱性クラスを排除しています:
- バッファオーバーフローなし
- ユーズアフターフリーなし
- ヌルポインタ参照なし
- コード内に
unsafeなし(Cargo.tomlのlint設定で禁止:unsafe_code = "deny")
399のcargoテスト+72のE2E SSHシナリオ
プロジェクトは399のcargoテストと72の追加E2E SSHシナリオでカバーされています:
| 種類 | 件数 | 説明 |
|---|---|---|
| 単体テスト | 約340 | 各モジュールを独立してテスト(10の*_tests.rsファイル) |
| 統合テスト | 50 | 完全なstdioシナリオ(バイナリ実行) |
| 適合性テスト | 1(6シナリオ) | JSONインターフェース契約の検証(ADR 0003) |
| Proptestテスト | 8 | プロパティベーステスト(制約誘導ファジング) |
| cargo合計 | 399 | |
| E2E SSHシナリオ | 72 | 実際のSSHサーバーによるDocker Compose環境 |
| cargo-fuzzハーネス | 9 | 非誘導ファジング(ランダム変異) |
E2E SSHテストは、完全なプロトコル、認証、セッション、セキュリティ、堅牢性、ログをカバーしています。実際のSSHサーバーによるDocker Compose環境で実行されます。
依存関係の監査
- CIで
cargo deny:ライセンスと既知の脆弱性(RustSecデータベース)をチェック cargo audit:依存関係のセキュリティ監査- ペダンティックモードの
cargo clippy:警告0件 - 直接依存関係は3つのみ:
serde、serde_json、toml— すべてRustコミュニティで広く監査済み
RBACアクセス制御
3段階の階層的信頼レベル:
| レベル | 用途 | 例 |
|---|---|---|
read | 読み取り専用 | healthcheck、status、list |
ops | 定常運用 | backup、deploy、restart |
admin | すべてのアクション | 設定、機密データ |
各アクションには必要なレベルがあります。各SSH接続には実効レベルがあります(authorized_keysの--levelまたはトークン認証経由)。
可視性タグ
垂直的なRBACに加えて、タグは水平的なフィルタリングを可能にします:forgejoタグを持つトークンは、opsレベルを持っていてもforgejoタグが付いたアクションのみを閲覧できます。
トークン認証
2つの認証モード:
- シンプルモード(
challenge_nonce = false):チャレンジ・レスポンスSHA-256(secret)— クライアントが秘密を知っていることを証明 - ノンスモード(
challenge_nonce = true):チャレンジ・レスポンスSHA-256(XOR_encrypt(secret || nonce, secret))、サーバーが送信するノンス付き。ノンスは認証成功のたびに再生成され、傍受されたプルーフのリプレイを防止
追加の防御
- コマンドごとのタイムアウト、プロセスグループkill(SIGTERMの後にSIGKILL)
- 認証失敗N回後のロックアウト(設定可能、デフォルト:3)
- 設定可能な外部コマンドによるオプションのIPバン
- ログ内の機密引数のマスキング(SHA-256)
- キャプチャ出力(stdout、stderr)のサイズ制限
- 環境のクリーンアップ:子プロセスに
env_clear()、PATHとSSH_FRONTIERE_SESSIONのみを注入
保証されない事項
ソフトウェアに完璧はありません。以下は既知かつ文書化された制限事項です:
8ビットXORカウンター
暗号実装は8192バイトに制限されたキーストリームのXORカウンターを使用しています。現在の用途(64文字のSHA-256プルーフ)には十分ですが、大量のデータの暗号化には設計されていません。
比較における長さの漏洩
定数時間比較で、比較値の長さが漏洩する可能性があります。実際にはSHA-256プルーフは常に64文字であるため、この漏洩は無視できます。
接続単位のレート制限
認証試行カウンターは各SSH接続にローカルです。攻撃者はN個の接続を開いてN × max_auth_failures回の試行が可能です。推奨:fail2ban、sshd MaxAuthTries、またはiptablesルールとの併用。
脆弱性の報告
公開イシューで脆弱性を報告しないでください。 責任ある開示のために、メンテナーに直接連絡してください。プロセスは貢献ガイドに記載されています。
依存関係
SSH-Frontièreは最小限の依存関係に関する厳格なポリシーを持っています。各外部クレートは加重マトリックス(ライセンス、ガバナンス、コミュニティ、サイズ、推移的依存関係)で評価されます。
| クレート | バージョン | 用途 | 正当性 |
|---|---|---|---|
serde | 1.x | シリアライゼーション/デシリアライゼーション | Rustのデファクトスタンダード、JSONとTOMLに必要 |
serde_json | 1.x | JSONレスポンス | プロトコル出力フォーマット |
toml | 0.8.x | 設定の読み込み | 設定用のRust標準 |
開発用依存関係:proptest(プロパティテストのみ、最終バイナリには含まれない)。
認可されたソース:crates.ioのみ。外部gitリポジトリは許可されていません。ポリシーはcargo denyで検証されています。