0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonスクリプトを軽量サンドボックスで割と安全に実行する

Last updated at Posted at 2025-02-26

LLMのPythonスクリプト出力を比較的安全に実行したい、そういう時って割とありますよね。使うのは自分だけなので怖いのは偶然危険なコードが出てきた時だけ、みたいなケースです。

でも世間に出回ってる情報はDockerを使ったもの (llm-sandbox) とか、WebAssemblyを使ったもの (Pyodide) とか、CPython以外の実装を使ったもの (PyPyのサンドボックス機能) とか、Webサービス向けの重量級のものばかり。軽かったであろう pysandbox はデザインに欠陥があり、制限も多く開発中止となっていました。

そんな中でさてどうしよう、サンドボックスのPython環境でもホストのPython環境と同じものが使えれば管理が楽なのに、と思いながら調べていました。

その結果、Pythonライブラリの中では決定打が見つからなかったものの、Linux環境の中では systemd-nspawn を読み込み専用マウントで使う方法を思いつき(但しルート権限が必要)、その systemd-nspawn に似ながらもルート権限が不要なbubblewrap (bwrap) を見つけ、その bwrap を使ってサンドボックスで Python スクリプトを実行するコードを書いてみました。

import os
import subprocess

home_dir = os.path.expanduser("~")

try:
    os.makedirs("/tmp/mysandbox_root")
except FileExistsError:
    pass

def sandbox_pyexec(code):
    proc = subprocess.Popen(
        ["bwrap", "--bind", "/tmp/mysandbox_root", "/", "--ro-bind", "/bin", "/bin", # システムファイルをRead-Onlyで共有する
         "--ro-bind", "/lib", "/lib", "--ro-bind", "/lib64", "/lib64", 
         "--ro-bind", "/usr", "/usr", "--ro-bind", "/etc", "/etc", # あんまり良くない
         "--ro-bind", home_dir + "/.local/lib", home_dir + "/.local/lib", # pip ライブラリをRead-Onlyで共有する
         "--ro-bind", home_dir + "/.local/bin", home_dir + "/.local/bin",
         "--ro-bind", home_dir + "/.local/share", home_dir + "/.local/share",
         "--bind", "/proc", "/proc", "--unshare-all", "--", # なるべくホストと非共有(systemd-nspawnと違ってプロセスリストは共有してるけど)
         "bash", "-c", "python -"],  # Pythonで標準入力のコードを実行
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True  # stdin / stdout を文字列として扱う
    )
    result, err = proc.communicate(code)
    return (result.strip(), err.strip())
    

r, err = sandbox_pyexec( """print("これはテストです")""")

print("stdout:", r)
print("stderr:", err)
# stdout: これはテストです
# stderr: 

r, err = sandbox_pyexec( """import os
os.system("ls /")""")

print("stdout:", r)
print("stderr:", err)
# stdout: bin
# etc
# home
# lib
# lib64
# proc
# usr
# stderr: 

r, err = sandbox_pyexec( """wrong python syntax here""")

print("stdout:", r)
print("stderr:", err)
# stdout: 
# stderr: File "<stdin>", line 1
#     wrong python syntax here
#           ^^^^^^
# SyntaxError: invalid syntax
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?