-- Views
December 17, 25
スライド概要
@deno/sandbox の紹介。
ミニマムな利用イメージ
個人開発サービスへの導入令
虎の穴ラボ株式会社は、主にとらのあな関連サービスのシステム開発を専門に担う、エンジニアの会社です。
@deno/sandbox を試す toranoana.deno #23 虎の穴ラボ オクタニ Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
自己紹介 奥谷 一陽 所属:虎の穴ラボ株式会社 仕事:Fantiaの開発 Ruby on Rails、 React 興味:Deno、TypeScript 最近購入:風都探偵(19) X:@okutann88 github:Octo8080X toranoana.deno 運営の1人 Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
@deno/sandbox Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
https://jsr.io/@deno/sandbox Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
@deno/sandbox - Deno Deploy上に隔離された軽量な Linux micro VMをサンドボックスを作成 - サンドボックス内で安全に - shell script - プロセスの実行 - js アプリ、 REPL - ファイル操作 ができる。 - この機能の SDKパッケージ Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
@deno/sandbox - サンドボックスは、 JS/TSから操作できる Linux micro VM - SSHアクセス - Linux micro vmへのワーキングディレクトリへの VSCodeでの参照 などもできる。 - AIが書いたコードの安全な利用 - どんなコードを書いてくるのか?事前設定できない - ガードレールを引いた中で動かしたい。 - 以前は、 deno land inc に連絡しないと使えなかったが 現在はその記述が無くなっている。 Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
https://jsr.io/@deno/sandbox Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
利用モチベーション - AI LLM 、vibe coding も良いが、 個人的にモチベーションが高いのは、 昨今話題に上がるような「コードを書かせるゲーム」の用途。 - 本体システムを壊さないように作った疑似コードではなく、 JS/TS そのものを書いて『安全に』ゲームにしたい。 Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
ミニマムな実行
import { Sandbox } from "@deno/sandbox" ;
await using sandbox = await Sandbox .create ();
await sandbox.sh `echo "Hello, world!"` ;
最小の構成として、サンドボックスで echoするだけ
$ deno -- env .\main.ts
deno -- env .\main.ts
✅ Granted env access to "WS_NO_BUFFER_UTIL" .
✅ Granted env access to "DENO_DEPLOY_TOKEN" .
✅ Granted env access to "DENO_SANDBOX_BASE_DOMAIN" .
✅ Granted env access to "DENO_DEPLOY_ENDPOINT" .
✅ Granted env access to "DENO_DEPLOY_CONSOLE_ENDPOINT" .
✅ Granted net access to "ams.sandbox-api.deno.net:443" .
Hello, world!
これだけでローカルマシンではなく、 denodeploy上のLinux micro VM に処理
を移譲させ、結果をもらうことがで
Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
Linux micro VMの中身
import { Sandbox } from "@deno/sandbox" ;
import { Sandbox } from "@deno/sandbox" ;
await using sandbox = await
Sandbox .create ();
await sandbox.sh `ls -la /` ;
await using sandbox = await
Sandbox .create ();
await sandbox.sh `cat /etc/os-release` ;
$ deno --env .\ls.ts
total 7180
drwxr-xr-x
1 root root
80 Nov 27 14:33 .
drwxr-xr-x
1 root root
80 Nov 27 14:33 ..
-rw-r--r-1 root root
0 Nov 17 17:09 .firecracker
drwxr-xr-x
1 daemon daemon 4096 Nov 29 06:37 app
lrwxrwxrwx 1 root root
7 Nov 17 17:09 bin -> usr/bin
drwxrwxrwt 10 root root
200 Nov 29 06:37 data
drwxr-xr-x
4 root root
2460 Nov 29 06:37 dev
drwxr-xr-x
1 root root
100 Nov 17 17:09 etc
-rwxr-xr-x
1 root root 7301040 Nov 27 01:37 fcinit
drwxr-xr-x
3 root root
45 Nov 17 17:09 home
drwxrwxrwt 2 daemon daemon
40 Nov 27 14:33 isolate
lrwxrwxrwx 1 root root
7 Nov 17 17:09 lib -> usr/lib
lrwxrwxrwx 1 root root
9 Nov 17 17:09 lib64 -> usr/lib64
drwx-----2 daemon daemon
3 Nov 26 20:41 mnt
drwxr-xr-x
2 root root
27 Nov 17 17:09 overlay
dr-xr-xr-x
113 root root
0 Nov 27 14:33 proc
drwxr-xr-x
18 root root
384 Nov 27 01:37 rom
drwxr-xr-x
2 root root
4096 Nov 27 14:33 root
drwxrwxrwt 6 root root
120 Nov 27 14:33 run
lrwxrwxrwx
1 root root
8 Nov 17 17:09 sbin -> usr/sbin
dr-xr-xr-x
12 root root
0 Nov 27 14:33 sys
drwxrwxrwt 9 root root
4096 Nov 29 06:37 tmp
drwxr-xr-x
12 root root
194 Sep 8 00:00 usr
drwxr-xr-x
5 root root
4096 Nov 27 14:33 var
$ deno --env -EN os.ts
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
- 中身は、 Debianベース
- apt install ~~はできなかった。
Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
実行履歴 実行履歴がサンドボックスの 作成単位で記録される Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
サンドボックス上で Deno プロセスを起動
import { Sandbox } from "@deno/sandbox" ;
await using sandbox = await Sandbox .create ();
任意のコードを
await sandbox. writeTextFile ("hello.ts" , "console.log('Hello,
Sandbox!');" );
サンドボックスにファイルとし
const child = await sandbox. spawn ("deno" , {
args: [ "run" , "hello.ts" ],
stdout: "piped" ,
});
// Read the output
for await (const chunk of child.stdout) {
console .log(new TextDecoder ().decode (chunk));
}
$ deno -- env -EN .\any-script-runner1.ts
Hello, Sandbox!
て書き込む
実行する
出力をストリーミングする
組み合わせとして deno add や、deno install もできるので、
外部パッケージの組み合わせも可能。
Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
いいね! Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
実践編 - 困ったこと - 任意のコードを設定して実行する =>意図しないコードが実行される 不適切なリソースアクセスだけが問題ではない! Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
実践編 - 困ったこと - 任意のコードを設定して実行する =>意図しないコードが実行される 不適切なリソースアクセスだけが問題ではない! 無限ループ !! while (true){ console.log(“thinking…”) } 開発者側が想定した通りの時間以内で終わってくれないと困る Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
実践編 - 知見
import { Sandbox } from "@deno/sandbox" ;
await using sandbox = await Sandbox .create ();
const scriptName = `${crypto.randomUUID()}.ts`
const scriptCode = `
console.log("process spawned script running");
while(true) {
console.log("still running...");
}
`
await sandbox. writeTextFile (scriptName,
scriptCode);
console .time ("MEASURE" );
const child = await sandbox. spawn ("deno" , {
args: [ "run" , scriptName],
stdout: "piped" ,
stderr: "piped" ,
signal: AbortSignal .timeout (3000 ),
});
console .log(await child.status)
console .timeEnd ("MEASURE" );
if(child.stdout === null ) {
throw new Error ("stdout is null" );
}
- sandboxで処理させるとき、
処理を持たずに無限ループだけなら、
すぐ停止できる。
- 無限ループ且つ中に処理を持っていると、
時間通りに停止ができない。
3000msで止めたいところ、
平気で10000ms超えたりする
- 無限ループ自体へ await delay(0)など
入れてあげるとすぐ止められる
Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
実践編 - 結論
async function
userCodeRun (abort:AbortController ):Promis
e<void >{
}
- 任意コードを必ず固定時間程度で停止は不可能
- sandboxへの実行の外で時間を管理し、
// sandbox で 任意コード実行
管理する。
function timeout (time: number ):
Promise <never > {
return new Promise ((_, reject ) => {
setTimeout (() => reject (new Error ("time
out!" )), time);
});
}
const abort = new AbortController ();
-
Promise.raceなどを使い、
後続処理は時間以内に始めるように考慮する。
- ただしsandboxも終わるように処理は非同期に
かけておく
try{
await Promise .race ([userCodeRun (abort),
timeout (3000 )]);
}catch (e){
console .log(e);
abort. abort ();
}
Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
これら踏まえて、ゲームを作る 技術スタック - Deno - Fresh - @deno/sandbox - babylonJS 無限ループ対策は、 生のfor、whileは実行前に禁止ワードとし て止めるようにしています。 再帰関数は回避できません。 https://deno-sandbox-api-test.octo8080x.deno.net/ Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
まとめ - @deno/sandbox により Deno Deploy上に隔離された Linux micro VM上で 安全に様々な処理ができる。 - 安全に任意のコードが実行できる。 不適切なリソースアクセスされないだけが『安全』ではない 想定時間通りに終えられないのも処理全体を通して安全なコードではない。 - 利用者の環境を考慮して、強制停止の戦略も考慮し使うことが必要 場合によっては字句解析など駆使して投げ込ませない運用も考える。 Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.
ありがとうございました Copyright (C) 2025 Toranoana Lab Inc. All Rights Reserved.