PraisonAI: SecurityPolicyにおけるコマンド/パス/インポートの制限は、デフォルトのSubprocessSandboxバックエンドでは全く適用されていません。
概要
praisonaiagents/sandbox/config.pyに定義されているSecurityPolicyは、allow_subprocess、allowed_paths、blocked_paths、allowed_commands、blocked_commands、allowed_imports、およびblocked_importsのフィールドを持つ設定データクラスです。そのstrict()というクラスメソッドは、「信頼できないコードのための厳格なセキュリティポリシー」を作成すると明記されており、allow_subprocess=False、allow_file_write=Falseを設定し、デフォルトのblocked_paths(/etc/passwd、/etc/shadow、~/.ssh、~/.aws、~/.config)およびblocked_commands(rm -rf、dd、mkfs、fdisk、shutdown、reboot)を継承します。
デフォルトのサンドボックスバックエンドであるSubprocess Sandbox (praisonai/sandbox/subprocess.py)は、入力を一時ファイルに書き込み、asyncio.create_subprocess_exec()を直接呼び出してコード/コマンドを実行します。この際、blocked_commands、blocked_imports、blocked_paths、allow_subprocess、またはallow_file_writeに対するいかなるチェックも行われません。リポジトリ内のすべてのサンドボックスバックエンドファイルを検索した結果、これらのフィールドが定義されているデータクラス以外の場所で参照されていないことが確認されました。実際に参照されているのは、allow_networkとmax_output_sizeのみです。
検証
Security Policyのstrict()設定で構成されたSandbox Config (sandbox_type="subprocess")と、実際のSubprocess Sandboxを使用した場合:
subprocess.run(['id'], ...)が実行され、uid=0(root)、gid=0(root)、groups=0(root)という結果が返されました。これは、allow_subprocess=Falseであるにもかかわらずです。
open('/etc/passwd').read()が実行され、/etc/passwdの内容が完全に読み込まれました。これは、/etc/passwdが明示的にblocked_pathsにリストされているにもかかわらずです。
rm -rfを含むシェルコマンドが実行され、実際にテスト用のディレクトリが作成され、その後削除されました(操作後にecho DELETEDが出力されたことで確認)。これは、"rm -rf"が明示的にblocked_commandsにリストされているにもかかわらずです。
すべてのアクションは、同じサンドボックス環境で一度に実行され、ポリシーのコマンド、パス、およびサブプロセスに関する制限が同時に機能しないことを確認しました。
影響
デフォルトのサブプロセスサンドボックスタイプに依存するすべてのデプロイメント(API自身の推奨する、信頼できないコードのための厳格な設定を含む)は、サブプロセスの作成、機密ファイルへのアクセス、または破壊的なコマンドの実行に対する実際の保護を受けません。サブプロセスは追加の依存関係を必要とせず、デフォルトのSandbox Config.sandbox_typeであるため、多くの実際のデプロイメントで、これは特殊なケースではなく、実際に使用されているバックエンドである可能性があります。
根本原因
セキュリティポリシーは、バックエンドに依存しない設定インターフェースとして設計されましたが、Subprocessサンドボックスには、allow_networkとmax_output_sizeのみが実装されていました。残りのフィールドは、完全にドキュメント化された設定として存在しますが、このバックエンドには対応する強制コードがありません。
推奨される対策
サブプロセスサンドボックスで、childプロセスを呼び出す前に、blocked_commands/blocked_imports/blocked_paths/allow_subprocess/allow_file_writeを適用するか、または、許可リスト方式のマッチングには既知の限界があるため、信頼できないコードに対して、実装済みのネイティブバックエンド(Landlock/Seatbelt)をデフォルトで使用し、強制されないサブプロセスバックエンドを使用しないようにします。SecurityPolicy.strict()が、そのフィールドを強制できないバックエンドに対してインスタンス化された場合に、例外を発生させることを検討してください。
影響を受けるパッケージ:
- pip (Python) praisonai: 影響あり <= 4.6.77、4.6.78で修正済み。