最近の coding agent は、外部 repo の調査から setup までかなり自然にやってくれます。
README を読んで、依存関係を入れて、dev server を起動して、エラーが出たら直す。個人開発だと、ここを任せられるだけでかなり楽です。
でも、未知の repo でいきなり npm install させるのは、ちょっと雑だと思っています。
危ないのは rm -rf / みたいな分かりやすいコマンドだけではありません。README、package.json、install script、network access、手元の .env がつながると、見た目は普通の setup でもかなり嫌な経路になります。
なので自分なら、denylist を増やす前に実行境界を決めます。
denylist は最後の網くらいに考える
terminal agent の安全対策でよくあるのが、危ない command を禁止するやり方です。
rm
curl
chmod
sudo
もちろん、ないよりはあった方がいいです。雑な事故は減ります。
ただ、これを安全性の中心に置くのは弱い。
curl を禁止しても、別の方法で network に出られるかもしれない。rm を禁止しても、上書きや移動で同じ結果になるかもしれない。shell は広いので、「この文字列が入っていたら止める」だけではすぐ抜け道が出ます。
CmdNeedle の paper でも、実際の command denylist の多くがかなり脆いと報告されています。細かい数字より、自分が気にしたいのはここです。
agent が shell を持っているなら、問題は「どの command を禁止するか」だけではない。
どこを読めるのか。どこに書けるのか。network に出られるのか。secret が見えているのか。package script を実行できるのか。
こっちを先に決めた方が、運用として強いです。
まず「読む」と「実行する」を分ける
未知の repo を触る時、自分は最初の段階を read-only inspection に寄せます。
いきなりこれをやらない。
npm install
npm run dev
先に見る。
git clone <repo-url> /tmp/agent-inspect/app
cd /tmp/agent-inspect/app
cat package.json
find . -maxdepth 2 -type f \
\( -name "package.json" -o -name "package-lock.json" -o -name "pnpm-lock.yaml" -o -name "yarn.lock" \)
install script も先に見ます。
grep -R "\"\\(preinstall\\|install\\|postinstall\\|prepare\\)\"" package.json .
ここでやりたいのは、完璧な malware scan ではありません。
まず「この repo は setup 時に何を実行しようとしているのか」を見ることです。postinstall、prepare、node -e、binary download、curl | sh、怪しい DNS lookup。そういうものが出てきたら、そのまま agent に任せない。
README に npm install && npm run dev と書いてあるだけなら、人間でも反射で打ちがちです。agent はもっと素直に打ちます。
だから instruction 側で、最初の一手を変えます。
## Unknown repository rules
- Start with read-only inspection.
- Do not run package install scripts during inspection.
- List the commands you want to run before executing them.
- Stop if setup requires shell scripts, binary downloads, or unknown network calls.
「安全に確認して」では弱いです。何を先に読むのか、何をまだ実行しないのかを書く。
npm install は --ignore-scripts から始める
Node project で一番悩ましいのは、依存関係の install がほぼ setup と同義になっているところです。
frontend だと npm install しないと型も build も見られない。でも install script をそのまま走らせるのは怖い。
最初はこれで十分です。
npm install --ignore-scripts
pnpm なら、状況に応じて script を無効にした install を使います。
pnpm install --ignore-scripts
これで「dependency tree を入れる」と「package script を実行する」を分けられます。
その後で、必要な script だけ読みます。
cat package.json
npm pkg get scripts
lockfile の差分も見ます。
git diff -- package-lock.json pnpm-lock.yaml yarn.lock
この段階で、agent にこう聞くのはありです。
install scripts を実行せずに依存関係だけ入れました。
次に実行したい package script と、その理由を列挙してください。
大事なのは、agent に「次の command を考えさせる」ことではなく、「次の command を説明させてから実行する」ことです。
secret が見える workspace で unknown script を走らせない
ここが一番現実的に事故りやすいと思っています。
個人開発の作業ディレクトリには、だいたい何かがあります。
.env
.env.local
~/.ssh
~/.aws
~/.config/gh
cloud provider の token
production DB の接続文字列
未知の repo を agent に触らせる時、これらが同じ実行環境から読めるのはよくない。
自分なら、clone 先を普段の workspace から分けます。
mkdir -p /tmp/agent-runs
git clone <repo-url> /tmp/agent-runs/app
cd /tmp/agent-runs/app
さらに、agent に渡す instruction もはっきり書きます。
## Secret boundary
- Do not read `.env`, `.env.local`, SSH keys, GitHub tokens, or cloud credentials.
- Do not inspect files outside this repository.
- If a command needs credentials, stop and ask.
本当は container や disposable VM に寄せる方がいいです。
ただ、毎回そこまでやると続かない人も多いはずです。なので最低ラインとして、普段の repo と secret の近くで unknown setup を走らせない。まずここからでいいと思います。
network access も「必要になったら開ける」にする
setup は network に出がちです。
package install、binary download、postinstall の telemetry、browser automation、API call。全部を永久に禁止するのは無理があります。
でも、初回 inspection で自由に出られる必要はありません。
自分なら agent にこういう順番を求めます。
1. file inspection
2. package scripts inspection
3. install without scripts
4. required network access の列挙
5. approval 後に実行
特に、setup 中に「別の command を実行して」「この URL を叩いて」「DNS から payload を読む」みたいな流れが出たら止めます。
Mozilla 0din の demo として報じられていた例でも、clean に見える repo と README の setup 手順を起点に、agent が親切に次の command へ進んでいく経路が問題になっていました。各段階は単体では派手に怪しく見えない。でも、つなげるとかなり危ない。
この手の話は「agent が愚かだから起きる」というより、agent が setup を完了しようと頑張るから起きます。
なので、頑張る範囲をこちらで切る。
AGENTS.md には長文の哲学より実行ルールを書く
repo instruction に security policy を書くなら、長い文章より短い実行ルールの方が効きます。
自分ならこのくらいにします。
## Unknown dependency and setup rules
- Inspect `package.json`, lockfiles, and install scripts before installing.
- Use `npm install --ignore-scripts` or equivalent for the first install.
- Do not run `preinstall`, `install`, `postinstall`, or `prepare` scripts without approval.
- Do not run commands copied from README until you have listed them first.
- Do not read `.env`, SSH keys, GitHub tokens, or cloud credential files.
- Ask before network access that is not package registry access.
- Summarize every shell command before execution.
この文章は地味です。でも、agent に期待する行動がかなり明確になります。
「安全にやって」だと、agent は安全そうな summary を出して、そのまま setup を進めることがあります。
「install script を approval なしで実行するな」なら、止まる場所ができます。
使い捨て環境で実行するならここまで見る
実際に build や test を回す段階では、どこかで script を実行する必要があります。
その時は、捨てられる環境に寄せます。
Docker なら雑にこういう形から始められます。
docker run --rm -it \
--network none \
-v "$PWD":/work:ro \
-w /work \
node:22-bookworm \
bash
read-only mount と network none なので、そのまま開発には使いにくいです。最初の確認用です。
install が必要なら、copy した disposable directory で実行します。
tmpdir=$(mktemp -d)
rsync -a --exclude node_modules . "$tmpdir/app"
cd "$tmpdir/app"
npm install --ignore-scripts
その後、どうしても script が必要なら、実行前に読む。
npm pkg get scripts
ここで postinstall が native binary を落とす、prepare が別 script を呼ぶ、README が追加 command を要求する。そういう場合は、agent に任せっぱなしにしない。
自分が使っている最小チェックリスト
毎回全部を厳密にやるのは無理です。
でも、未知の repo を agent に触らせるなら、このくらいは見ます。
Workspace:
- 普段の作業 repo ではなく temporary directory に clone したか
- agent に不要な parent directory を見せていないか
Secrets:
- `.env` や cloud credentials が workspace 内にないか
- shell profile 経由で token が入らないか
Package scripts:
- preinstall / install / postinstall / prepare を読んだか
- 初回 install は scripts 無効で行ったか
Network:
- setup に必要な外部アクセスを説明できるか
- binary download や unknown URL がないか
Approval:
- agent が実行したい command を先に list 化したか
- その command が何を読むか、何を書くか説明できるか
このチェックリストは完璧ではありません。
ただ、agent に npm install を丸投げするよりはずっとましです。特に個人開発では、production token や admin credential が手元に近いことが多いので、secret boundary だけでも効きます。
まとめ
AI agent の security は、agent の性格や賢さだけで決まりません。
むしろ、実行環境の方が大きいです。
未知の repo では、まず読む。install script を無効にして依存関係を見る。secret が見える場所で setup を走らせない。network access は必要になってから開ける。agent には、command を実行する前に列挙させる。
denylist はあっていい。でも、それを主役にしない。
agent が親切に作業を進められる時代だからこそ、親切さが届く範囲をこちらで決めておく必要があります。