DENO_AUDIT_PERMISSIONSを使ってみよう ~ npmパッケージがいかに余計な権限を要求しているかを見てみる
on 2025/09/24 (水)
DENO_AUDIT_PERMISSIONS がDeno v2.5から使えるようになった
DENO_AUDIT_PERMISSIONS を使うと、JSON Lines形式で、プログラムが要求したパーミッションの一覧を吐き出してくれる
例
code:shell
DENO_AUDIT_PERMISSIONS=./perm.jsonl deno run --allow-all npm:eslint
code:jsonl
{"v":1,"datetime":"2025-09-24T08:01:47Z","permission":"env","value":"TERM"}
{"v":1,"datetime":"2025-09-24T08:01:47Z","permission":"env","value":"CI"}
{"v":1,"datetime":"2025-09-24T08:01:47Z","permission":"env","value":"TEAMCITY_VERSION"}
{"v":1,"datetime":"2025-09-24T08:01:47Z","permission":"env","value":"COLORTERM"}
...
npmエコシステムが震撼
npmの post-install 時に悪意のある攻撃スクリプト bundle.js が実行されることで機密情報の取得および自身の拡散を行うとのこと
ちなみにDenoはデフォルトだと post-install 時のスクリプトを実行しない (--allow-scripts フラグが必要)
今回の攻撃は @ctrl/tinycolor のようにnpmエコシステム(a.k.a dependency hell)の底に近いものが被害に遭ったことで、このライブラリを間接的にでも使用している膨大なアプリ・ライブラリがリスクにさらされた 生成AIパワーで「ちょっとしたライブラリは自前で書いて管理下におくことも現実的な選択肢になった」と言えなくもないが、依存関係の底の底に近いものを置き換えるのはさすがに厳しい
少なくとも、今あなたが作っているものが、その依存ライブラリも含めて「どのようなI/Oや環境変数へのアクセスを行っているのか」を把握すれば、
依存ライブラリを少しでも減らして潜在的リスクを下げる
現時点で必要と分かっている権限だけを明示的に Deno に与え、仮に依存ライブラリのバージョンが上がったりしても、他の余計なことはさせないようにする
という一歩先の対策をすることが可能
DENO_TRACE_PERMISSIONS との合わせ技
Pro tip: DENO_AUDIT_PERMISSIONS に加え DENO_TRACE_PERMISSIONS を有効化すると、その権限を要求している箇所のスタックトレースも出力される
code:shell
DENO_TRACE_PERMISSIONS=1 DENO_AUDIT_PERMISSIONS=./perm.jsonl deno run --allow-all npm:eslint
code:jsonl
{"v":1,"datetime":"2025-09-24T07:50:12Z","permission":"env","value":"TERM","stack":["Object.getEnv as get (ext:deno_os/30_os.js:124:10)","denoEnvGet (ext:deno_node/_process/process.ts:27:21)","Object.get (ext:deno_node/_process/process.ts:44:22)","supportsColor (file:///tmp/my-app/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:65:10)","file:///tmp/my-app/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:133:25","Object.<anonymous> (file:///tmp/my-app/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:137:3)","Module._compile (node:module:757:34)","loadMaybeCjs (node:module:782:10)","Object.Module._extensions..js (node:module:767:12)","Module.load (node:module:675:32)"]} {"v":1,"datetime":"2025-09-24T07:50:12Z","permission":"env","value":"CI","stack":["Object.getEnv as get (ext:deno_os/30_os.js:124:10)","denoEnvGet (ext:deno_node/_process/process.ts:27:21)","Object.has (ext:deno_node/_process/process.ts:68:32)","supportsColor (file:///tmp/my-app/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:83:11)","file:///tmp/my-app/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:133:25","Object.<anonymous> (file:///tmp/my-app/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:137:3)","Module._compile (node:module:757:34)","loadMaybeCjs (node:module:782:10)","Object.Module._extensions..js (node:module:767:12)","Module.load (node:module:675:32)"]} ...
ちょっと読みにくいが、気合で読むと、TERM や CI といった環境変数を読み取ろうとしているのは、supports-color だと分かる DENO_TRACE_PERMISSIONS だけを有効にして、 --allow-all を取り去ってみると、実行時に都度、パーミッションの要求がプロンプトされるようになる。プログラムが要求する権限を対話的に把握したい場合に有用
https://scrapbox.io/files/68d3b4d4b9811b520ef1322a.png
Xでの声
MCPサーバーをDenoで書いて、パーミッションを絞る話
ランタイム agnostic (=NodeでもDenoでもBunでも動く) なパッケージを作ってnpmで配布するが、開発時にDenoを使って最小限のパーミッションで動作することを確認する開発スタイルの提案
@__syumai: こんな感じで、Node.js向けのコマンドを作る時に、ついでにDenoのPermission flagがどこまで絞れてるか確認してから配布してもらえると、リスクを理解した上で許可しつつ使えるので、皆さんやっていってくれるとありがたいなと思います… @yusuktan: Denoでnpmパッケージ動かすときに --allow-env=MY_AWESOME_ENV みたいに環境変数アクセスを絞ってやれば安全性が高まって嬉しい、というのは大いにその通りなんですが、𝑫𝑬𝑷𝑬𝑵𝑫𝑬𝑵𝑪𝒀 𝑯𝑬𝑳𝑳のどこかに Object.keys(process.env) みたいにすべての環境変数を列挙しようとするやつがいると 例: debug
まとめ
DENO_AUDIT_PERMISSIONS がv2.5から使えるようになった
npmエコシステムが脅威にさらされたり、AIが生成した「必ずしも信頼できない」コードを実行することが多くなった今、Denoのパーミッションモデルが再評価されていると俺の中で話題に
DENO_TRACE_PERMISSIONS との合わせ技が有効
MCPサーバーやnpmパッケージの実装者の視点でも、Denoを使って、「このサーバーやパッケージを動かすのに必要な最低限の権限は何なのか」を考えながらやると良いのでは
古くからのnpmパッケージはワイルドに全環境変数にアクセスしたりしていて、現実は厳しい