パーミッション#

パーミッションは、Node.js プロセスがどのシステムリソースにアクセスできるか、またはそれらのリソースに対してどのようなアクションを実行できるかを制御するために使用できます。

  • プロセスベースのパーミッションは、Node.js プロセスのリソースへのアクセスを制御します。リソースは完全に許可または拒否されるか、関連するアクションを制御できます。たとえば、書き込みを拒否しながらファイルシステムの読み取りを許可することができます。この機能は悪意のあるコードから保護するものではありません。Node.js のセキュリティポリシーによると、Node.js は実行を要求されたすべてのコードを信頼します。

パーミッションモデルは「シートベルト」アプローチを実装しており、信頼されたコードが意図せずファイルを変更したり、明示的にアクセスが許可されていないリソースを使用したりするのを防ぎます。これは、悪意のあるコードが存在する場合のセキュリティを保証するものではありません。悪意のあるコードはパーミッションモデルをバイパスし、パーミッションモデルによって課される制限なしに任意のコードを実行できます。

潜在的なセキュリティ脆弱性を見つけた場合は、セキュリティポリシーを参照してください。

プロセスベースのパーミッション#

パーミッションモデル#

安定性: 2 - Stable

Node.js パーミッションモデルは、実行中に特定のリソースへのアクセスを制限するメカニズムです。この API は --permission フラグの背後に存在し、有効にすると、利用可能なすべてのパーミッションへのアクセスが制限されます。

利用可能なパーミッションは --permission フラグによって文書化されています。

--permission を付けて Node.js を起動すると、fs モジュールを介したファイルシステムへのアクセス、ネットワークへのアクセス、プロセスの生成、node:worker_threads の使用、ネイティブアドオンの使用、WASI の使用、およびランタイムインスペクターの有効化が制限されます(SIGUSR1 のリスナーは作成されません)。

$ node --permission index.js

Error: Access to this API has been restricted
    at node:internal/main/run_main_module:23:47 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'FileSystemRead',
  resource: '/home/user/index.js'
} 

プロセスの生成とワーカースレッドの作成へのアクセスを許可するには、それぞれ --allow-child-process--allow-worker を使用します。

ネットワークアクセスを許可するには --allow-net を使用し、パーミッションモデルを使用する際にネイティブアドオンを許可するには --allow-addons フラグを使用します。WASI の場合は --allow-wasi フラグを使用します。

ランタイム API#

--permission フラグを介してパーミッションモデルを有効にすると、process オブジェクトに新しいプロパティ permission が追加されます。このプロパティには1つの関数が含まれています。

permission.has(scope[, reference])#

実行時にパーミッションをチェックするための API 呼び出し (permission.has())

process.permission.has('fs.write'); // true
process.permission.has('fs.write', '/home/rafaelgss/protected-folder'); // true

process.permission.has('fs.read'); // true
process.permission.has('fs.read', '/home/rafaelgss/protected-folder'); // false 
ファイルシステムパーミッション#

パーミッションモデルは、デフォルトで node:fs モジュールを介したファイルシステムへのアクセスを制限します。これは、ユーザーが node:sqlite モジュールなどの他の手段を介してファイルシステムにアクセスできなくなることを保証するものではありません。

ファイルシステムへのアクセスを許可するには、--allow-fs-read および --allow-fs-write フラグを使用します。

$ node --permission --allow-fs-read=* --allow-fs-write=* index.js
Hello world! 

デフォルトでは、アプリケーションのエントリーポイントは許可されたファイルシステムの読み取りリストに含まれます。例えば、

$ node --permission index.js 
  • index.js は許可されたファイルシステムの読み取りリストに含まれます。
$ node -r /path/to/custom-require.js --permission index.js. 
  • /path/to/custom-require.js は許可されたファイルシステムの読み取りリストに含まれます。
  • index.js は許可されたファイルシステムの読み取りリストに含まれます。

両方のフラグに有効な引数は次のとおりです。

  • * - それぞれ、すべての FileSystemRead または FileSystemWrite 操作を許可します。
  • 現在の作業ディレクトリからの相対パス。
  • 絶対パス。

  • --allow-fs-read=* - すべての FileSystemRead 操作を許可します。
  • --allow-fs-write=* - すべての FileSystemWrite 操作を許可します。
  • --allow-fs-write=/tmp/ - /tmp/ フォルダへの FileSystemWrite アクセスを許可します。
  • --allow-fs-read=/tmp/ --allow-fs-read=/home/.gitignore - /tmp/ フォルダ /home/.gitignore パスへの FileSystemRead アクセスを許可します。

ワイルドカードもサポートされています。

  • --allow-fs-read=/home/test* は、ワイルドカードに一致するすべてのものへの読み取りアクセスを許可します。例: /home/test/file1/home/test2

ワイルドカード文字 (*) を渡した後は、後続のすべての文字は無視されます。例えば、/home/*.js/home/* と同様に機能します。

パーミッションモデルが初期化されると、指定されたディレクトリが存在する場合、自動的にワイルドカード(*)が追加されます。例えば、/home/test/files が存在する場合、それは /home/test/files/* として扱われます。しかし、ディレクトリが存在しない場合、ワイルドカードは追加されず、アクセスは /home/test/files に限定されます。まだ存在しないフォルダへのアクセスを許可したい場合は、明示的にワイルドカードを含めるようにしてください: /my-path/folder-do-not-exist/*

npx でパーミッションモデルを使用する#

npx を使用して Node.js スクリプトを実行している場合、--node-options フラグを渡すことでパーミッションモデルを有効にできます。例えば、

npx --node-options="--permission" package-name 

これは、npx プロセス自体に影響を与えることなく、npx によって生成されたすべての Node.js プロセスの NODE_OPTIONS 環境変数を設定します。

npx での FileSystemRead エラー

上記のコマンドは、Node.js がパッケージを見つけて実行するためにファイルシステムの読み取りアクセスを必要とするため、おそらく FileSystemRead の不正アクセスエラーをスローします。これを避けるには、

  1. グローバルにインストールされたパッケージを使用する 以下を実行して、グローバルな node_modules ディレクトリへの読み取りアクセスを許可します。

    npx --node-options="--permission --allow-fs-read=$(npm prefix -g)" package-name 
  2. npx キャッシュを使用する パッケージを一時的にインストールしたり、npx キャッシュに依存している場合は、npm キャッシュディレクトリへの読み取りアクセスを許可します。

    npx --node-options="--permission --allow-fs-read=$(npm config get cache)" package-name 

通常 node に渡す引数(例:--allow-* フラグ)も --node-options フラグを介して渡すことができます。この柔軟性により、npx を使用する際に必要に応じてパーミッションを簡単に設定できます。

パーミッションモデルの制約#

このシステムを使用する前に知っておくべき制約があります。

  • モデルはワーカースレッドに継承されません。
  • パーミッションモデルを使用すると、次の機能が制限されます。
    • ネイティブモジュール
    • ネットワーク
    • 子プロセス
    • ワーカースレッド
    • インスペクタープロトコル
    • ファイルシステムアクセス
    • WASI
  • パーミッションモデルは、Node.js 環境がセットアップされた後に初期化されます。しかし、--env-file--openssl-config などの特定のフラグは、環境の初期化前にファイルを読み取るように設計されています。その結果、そのようなフラグはパーミッションモデルのルールの対象外となります。v8.setFlagsFromString を介してランタイムで設定できる V8 フラグにも同じことが当てはまります。
  • パーミッションモデルが有効になっている場合、OpenSSL エンジンをランタイムで要求することはできず、組み込みの crypto、https、および tls モジュールに影響します。
  • パーミッションモデルが有効になっている場合、ランタイムでロード可能な拡張機能はロードできず、sqlite モジュールに影響します。
  • node:fs モジュールを介して既存のファイルディスクリプタを使用すると、パーミッションモデルがバイパスされます。
制限と既知の問題#
  • シンボリックリンクは、アクセスが許可されているパスのセットの外にある場所であっても追跡されます。相対シンボリックリンクは、任意のファイルやディレクトリへのアクセスを許可する可能性があります。パーミッションモデルを有効にしてアプリケーションを起動する場合、アクセスが許可されているパスに相対シンボリックリンクが含まれていないことを確認する必要があります。