AI-Scientistプロジェクトのセキュリティメカニズム:コードサンドボックスとデータプライバシープロテクションの実装

AI-Scientistプロジェクトのセキュリティメカニズム

AI-Scientistは自動科学発見ツールとして設計されており、そのセキュリティ設計は実験信頼性とデータ安全性に直結します。本文ではコードサンドボックスとデータプライバシープロテクションの実装を解説し、開発者向けに安全なAI実験環境構築の指針を提供します。

セキュリティアーキテクチャの概要

AI-Scientistのセキュリティ設計は以下の要素から構成されています:

  • 多層的なアクセス制御
  • コンテナベースの実行隔離
  • リソース制限とプロセス分離
  • 実験ライフサイクル管理
  • データ処理におけるプライバシーポリシー

コンテナ化された実行環境

プロジェクトのexperimentalディレクトリにあるDockerfileは最小権限原則に基づいて構成されています:

FROM python:3.11-bullseye
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget=1.21-1+deb11u1 \
    git=1:2.30.2-1+deb11u2 \
    build-essential=12.9 \
    libssl-dev=1.1.1w-0+deb11u1 \
    zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \
    && rm -rf /var/lib/apt/lists/*
RUN useradd -m aiuser
USER aiuser
WORKDIR /app
RUN chown -R aiuser:aiuser /app

この構成により、以下のセキュリティメリットが実現されています:

  • 固定バージョン依存によるサプライチェーン攻撃防止
  • 不要なパッケージインストール回避
  • APTキャッシュ削除によるイメージサイズ最適化
  • 非rootユーザーでの実行によるリスク軽減

実験コードの実行制御

perform_experiments.pyにおいて実行制御が行われています:

def run_experiment(folder_name, run_num, timeout=7200):
    cwd = osp.abspath(folder_name)
    shutil.copy(osp.join(folder_name, "experiment.py"), 
                osp.join(folder_name, f"run_{run_num}.py"))
    command = ["python", "experiment.py", f"--out_dir=run_{run_num}"]
    try:
        result = subprocess.run(command, cwd=cwd, 
                               stderr=subprocess.PIPE, text=True, timeout=timeout)
        if result.stderr:
            print(result.stderr, file=sys.stderr)
        if result.returncode != 0:
            print(f"Run {run_num} failed with return code {result.returncode}")
            if osp.exists(osp.join(cwd, f"run_{run_num}")):
                shutil.rmtree(osp.join(cwd, f"run_{run_num}"))
            stderr_output = result.stderr
            if len(stderr_output) > MAX_STDERR_OUTPUT:
                stderr_output = "..." + stderr_output[-MAX_STDERR_OUTPUT:]
            next_prompt = f"Run failed with the following error {stderr_output}"
        else:
            with open(osp.join(cwd, f"run_{run_num}", "final_info.json"), "r") as f:
                results = json.load(f)
            results = {k: v["means"] for k, v in results.items()}
            next_prompt = f"Run {run_num} completed. Results: {results}"
        return result.returncode, next_prompt
    except TimeoutExpired:
        print(f"Run {run_num} timed out after {timeout} seconds")
        if osp.exists(osp.join(cwd, f"run_{run_num}")):
            shutil.rmtree(osp.join(cwd, f"run_{run_num}"))
        next_prompt = f"Run timed out after {timeout} seconds"
        return 1, next_prompt

この実行制御では以下のような安全機能が含まれています:

  • 出力ディレクトリ指定制限
  • タイムアウト制御
  • エラーログのサイズ制限
  • 失敗時の自動クリーンアップ
  • 結果JSON検証

データプライバシープロテクション

data/enwik8/prepare.pyにおけるデータ処理:

n = len(data)
num_test_chars = 5000000
train_data = data[: -2 * num_test_chars]
val_data = data[-2 * num_test_chars: -num_test_chars]
test_data = data[-num_test_chars:]

train_ids = encode(train_data)
val_ids = encode(val_data)
test_ids = encode(test_data)

print(f"train has {len(train_ids):,} tokens")
print(f"val has {len(val_ids):,} tokens")
print(f"test has {len(test_ids):,} tokens")

train_ids = np.array(train_ids, dtype=np.uint16)
val_ids = np.array(val_ids, dtype=np.uint16)
test_ids = np.array(test_ids, dtype=np.uint16)

train_ids.tofile(os.path.join(os.path.dirname(__file__), 'train.bin'))
val_ids.tofile(os.path.join(os.path.dirname(__file__), 'val.bin'))
test_ids.tofile(os.path.join(os.path.dirname(__file__), 'test.bin'))

この処理では以下のような保護措置が採用されています:

  • トレーニング/テストデータ分割
  • 文字列エンコードによる明文防止
  • バイナリ形式保存
  • データ型最適化
  • データ量記録

改善点と対策

リスクタイプ現状改善案実装難易度
データ明文通信未暗号化SSL/TLS導入
データ脱敏不足未実施PII検出ツール導入
アクセスログ欠如未記録アクセスログ記録
モデル重み保護明文保存暗号化保存
データ廃棄戦略未定義ライフサイクル管理

推奨改善点:

  1. データ暗号化通信の実装
  2. データ脱敏ツールの統合
  3. アクセスログシステムの構築
  4. モデルファイル暗号化
  5. データライフサイクル管理

セキュリティベストプラクティス

Dockerセキュリティ強化:

RUN useradd -m -d /home/aiuser -s /bin/bash aiuser
RUN chown -R aiuser:aiuser /app
USER aiuser
docker run --read-only --tmpfs /tmp --tmpfs /var/run ...
docker run --cap-drop=ALL --security-opt=no-new-privileges ...

実行制御の強化:

command = ["python", "experiment.py", f"--out_dir=run_{run_num}"]
result = subprocess.run(
    command, 
    cwd=cwd, 
    stderr=subprocess.PIPE, 
    text=True, 
    timeout=timeout,
    preexec_fn=lambda: os.setuid(os.getuid()),
)

データ保護の強化:

from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher_suite = Fernet(key)
encrypted_data = cipher_suite.encrypt(train_ids.tobytes())
with open('train.enc', 'wb') as f:
    f.write(encrypted_data)

タグ: Docker コンテナ化 データ暗号化 モデルセキュリティ セキュリティアーキテクチャ

8月21日 09:54 投稿