何が起きたか:GitHub Package Firewallの公開プレビュー開始

GitHubは2026年10月20日、依存パッケージの取得をインラインで検査・保護する「GitHub Package Firewall」の公開プレビューを開始しました[1, 2, 3, 4]。

本機能は、データ所在地型(data-resident)を含むGitHub Enterprise Cloudの顧客向けに提供されています[1, 2, 4]。プレビュー期間中は無料で利用可能であり、一般提供の開始後は従量課金となる予定です[2, 4]。なお、公開プレビュー期間中は仕様が変更される可能性があります[2]。

現時点で対応しているパッケージエコシステムはnpmのみです[1, 5, 6, 3, 7, 4]。

Package Firewallは、開発端末、CIランナー、AIエージェントなどのエンドポイントと、上流のパッケージレジストリとの間に位置します[8, 9]。パッケージ一覧を取得するメタデータ要求と実際のパッケージ本体のダウンロードの双方がFirewallを経由し、設定されたセキュリティポリシーに基づいて通過時に評価・遮断されます[8, 6, 9, 10]。

補足:インライン検査とは

通信経路の途中に介在し、リクエストやデータのダウンロードをリアルタイムに評価して、ポリシーに合致しない通信をその場で遮断する仕組みです。

後輩パッケージの検査って、CIのビルド時やリポジトリへのコミット時に行うセキュリティスキャンとは何が違うんですか?

先輩通信経路そのものに介在する点だね。手元にパッケージが入ってきてからスキャンする形だと、取得やインストールの瞬間に動く処理を止められないことがあるんだよ。

後輩パッケージが手元に届く手前で通信を止めるから、水際で防げるわけですね。

なぜ今インストール時の保護が必要か:ライフサイクルスクリプトの脅威と検知の隙間

npmの依存パッケージに定義されている preinstall や install、postinstall などのライフサイクルスクリプトは、パッケージのインストール工程で自動的に実行されます[11]。POSIXシステムではこれらのスクリプト行が /bin/sh に渡されて実行されるため、アプリケーション本体のコードを起動する前であっても、開発端末やCIホスト上でシェル経由の処理が実行されます[11]。

パッケージリポジトリやCI/CD環境の弱点を狙うサプライチェーン攻撃では、盗み出した認証情報を利用して攻撃を拡散させたり、後続の悪用に利用したりするパターンが報告されています[11, 12]。

従来の依存関係管理では、アドバイザリの登録や通知のタイミングに時間差が生じる課題がありました。DependabotのマルウェアアラートはGitHub Advisory Databaseの情報に依存していますが、新しいマルウェアがデータベースに登録されてアラートが発報されるまでには時間を要する場合があります[13, 14, 15]。また、アラートの対象となるのはGitHubによってレビューされたアドバイザリに限られます[13, 14, 15]。

さらに、Dependabotによる通常のversion update PRには、新リリースがレジストリで公開されてから少なくとも3日間の既定クールダウン期間が設けられています[16, 17]。セキュリティ修正を伴うsecurity update PRは即時に作成されますが、通常の更新PRは公開直後のリスクを避けるために待機時間が存在します[16, 17]。

このように、公開直後の悪意あるパッケージが開発端末やCI環境で直接インストールされた場合、アドバイザリ登録やPR作成を待つ仕組みだけでは、手元でのスクリプト実行を直前に防ぐことが困難でした。

関連するエコシステム側の対策として、GitHubが告知しているnpm v12の変更では、allowScripts の既定値がオフになり、依存パッケージのインストールスクリプト(preinstall、install、postinstall)はプロジェクトで明示的に許可されない限り実行されなくなります[18, 19]。Dependabotのクールダウン仕様(通常更新とセキュリティ更新の分離)やマルウェアアラートの審査要件を踏まえつつ、パッケージ取得時の水際保護とツール側の実行制御を適切に切り分けて捉える必要があります[20]。

後輩Dependabotのアラートがあるから大丈夫だと思っていましたが、アドバイザリの登録やレビューにはどうしても時間差が生じるんですね。

先輩そうだね。公開直後に悪意あるコードを仕込んだパッケージが取得されると、データベースに反映される前にスクリプトが動いてしまう恐れがあるんだよ。

後輩だからこそ、メタデータ要求やダウンロードの段階で、既知マルウェアや新しく追加されたスクリプトなどのポリシー条件に合うパッケージを遮断する多層防御が必要になるわけですね。

何が変わるか:取得時の検査・遮断ポリシーと依存関係管理の役割分担

Package Firewallは、エンドポイントからの取得要求に対して以下の5つのポリシーを設定し、インラインで検査を行います[21, 24, 26, 28, 22, 25, 23, 27]。

  1. 既知マルウェア制御(Known malware control): GitHub Advisory Databaseのアクティブなマルウェアアドバイザリと一致するパッケージを遮断します。既定で有効(On)です[21, 22, 23]。
  2. 脆弱性深刻度制御(Vulnerability severity control): 遮断対象とする最低深刻度を「Criticalのみ」「High以上」「Medium以上」「全深刻度(Any severity)」から選択できます。既定値は「Criticalのみ」です[21]。
  3. 最低パッケージ年齢(Minimum package age): 公開から設定した日数よりも新しいバージョンを遮断します。設定範囲は1〜365日で、既定値は1日です。0を指定することでこの制御を無効化できます[24, 25]。
  4. 最近追加されたスクリプトの制御(Recently added scripts control): preinstall や postinstall など、パッケージが最近追加したインストール時実行スクリプトを確認して遮断します。既定で有効(On)です[26, 22, 27]。
  5. アテステーション・ダウングレード制御(Attestation downgrade control): 過去のバージョンにSLSAアテステーションが存在していたパッケージにおいて、要求されたバージョンにアテステーションが存在しない場合にダウンロードを遮断します。既定で有効(On)です[28, 22]。
ポリシー名判定条件・動作設定可能範囲既定値
既知マルウェア制御GitHub Advisory Databaseのアクティブなマルウェアアドバイザリと一致するパッケージを遮断有効 / 無効有効(On)
脆弱性深刻度制御設定した最低深刻度以上の脆弱性アドバイザリに一致するパッケージを遮断Criticalのみ / High以上 / Medium以上 / 全深刻度Criticalのみ
最低パッケージ年齢バージョン公開から設定日数未満のパッケージ取得を遮断1〜365日(0で無効化)1日
最近追加されたスクリプト最近追加されたインストール時スクリプト(preinstall/postinstall等)を確認して遮断有効 / 無効有効(On)
アテステーション・ダウングレード以前SLSAアテステーションがあったパッケージでのアテステーション欠落を遮断有効 / 無効有効(On)

ソフトウェアサプライチェーンの保護においては、各工程に応じたツールの役割分担を整理することが有効です[37, 33, 34, 31, 36]。

  • package.json: パッケージ名ごとにバージョン範囲を宣言し、インストール候補を制約します[29]。
  • package-lock.json: 解決された依存関係ツリーを記録し、後続のインストールで同一のツリーを再現します[30, 31]。
  • Dependabot: 既知の脆弱性を検知し、パッチを含む修正バージョンへの更新プルリクエスト(PR)を作成します[32, 31]。
  • Dependency Review: プルリクエストの差分を検査し、追加・更新・削除される依存関係や脆弱性をマージ前に検知します[33, 34, 35, 31, 36]。
  • npm v12: 依存パッケージのインストールスクリプト実行を既定で無効化し、プロジェクトの明示的な許可リストで管理します[18, 26, 19, 31, 36]。
  • Package Firewall: 開発端末やCIランナーがレジストリからパッケージを取得する際に、メタデータ要求とダウンロードをインラインで判定して遮断します[37, 33, 34, 9, 31, 36]。

JFrog Artifactoryとの連携は実験的サポートとして提供されています[38]。この構成では、Artifactoryインスタンスの管理者権限とパーソナルアクセストークン(PAT)を用いて、Package Firewallを上流とするnpm Remoteを作成し、内部リポジトリと共にvirtual npm repositoryへ組み込みます[38, 39, 40]。エンドポイントは引き続きArtifactoryを参照します[39]。

この構成により、Artifactoryが内部パッケージの保管やキャッシュ、複数リポジトリの集約を担い、Package Firewallが外部パッケージ取得に対するポリシー判定を担当します[39, 41]。なお、Firewallを迂回して公開npmレジストリから直接取得するRemoteが残っているとバイパス経路となるため、virtual repositoryから除外する必要があります[38, 39, 42]。

誰に影響するか:実務環境への導入手順と運用上の制約・例外管理

実務環境への導入では、開発端末、CIランナー、AIコーディングエージェントなど、npmを実行する各環境のuser-level .npmrc を設定します[43, 44]。

レジストリURLを企業専用のFirewallエンドポイントへ向け、認証トークンを設定します[43, 44]:

registry=https://package-firewall.githubapp.com/npm/enterprises/ENTERPRISE
//package-firewall.githubapp.com/npm/enterprises/ENTERPRISE/:_authToken=${GITHUB_TOKEN}

各リクエストには、対象Enterpriseのメンバーであるユーザーまたはbotアカウントに紐づく認証トークンが必要です[45, 46, 47]。必要な権限は公開リポジトリへの読み取り専用(Read-only)権限にとどまります[45, 47]。CI環境などで使用するトークンはCI secretなどに安全に保管し、リポジトリにコミットしない運用が案内されています[45, 44, 46, 47]。

ポリシーの設定権限は、Enterprise administrators(管理者)およびEnterprise security managersにあります[48]。他の利用者に権限を委譲する場合は、適切なfine-grained permissionを含むcustom roleを割り当てます[48]。

パッケージの取得が遮断された場合、npmのコマンド出力やCI/CDの実行ログに例外申請用のURLが表示されます[49]。利用者はそのURLから申請フォームを開き、対象リポジトリ、エコシステム、パッケージ名、バージョン、申請理由、補足コメントを提出します[49]。

申請はエンタープライズ管理者またはセキュリティマネージャーが審査します[50]。最低パッケージ年齢ポリシーによって緊急のセキュリティ修正を含む新バージョンがブロックされた場合や、企業所有のパッケージを許可する場合などが理由として想定されています[51]。承認者は対象バージョンを * に変更して全バージョンへの適用に広げることも可能であり、承認されたバイパス例外はポリシーに追加され、後から削除することもできます[50]。

実務での導入にあたっては、以下の制約と留意事項を考慮する必要があります。

  1. 検出精度指標やSLAの未公表: 公開告知および公式ドキュメントにおいて、Package Firewallの検出精度(precision、recall、誤検知率、見逃し率)や評価用データセット、評価方法は公表されていません[52]。GitHubは誤って遮断される事象への対処として例外申請手順を案内していますが、誤遮断の発生頻度や具体例は公表していません[53]。また、既知マルウェア制御の見逃し率やアドバイザリ反映時間、審査条件や更新SLAも確認できないため、すべての攻撃を完全に防ぐものとして扱うのではなく、多層防御の一環として運用することが求められます[23, 54]。
  2. 非レジストリ依存の迂回経路: npmのregistry設定を変更しても、Gitリポジトリを直接参照する依存(git コマンドによる取得)や、lockfile内に別ホストのtarball URLが明記されている依存など、非レジストリ依存の通信はFirewallを経由しない可能性があります[55, 56, 57, 58]。社内の通信経路や依存定義において、Firewallを通過しない取得経路が存在しないかを個別に確認することが推奨されます[55, 56, 57, 58]。また、プロキシ併用時にも公開レジストリへの直接経路を残さない設定の確認が必要です[59]。
  3. プレビュー段階における仕様確認: 本機能は現在パブリックプレビュー段階にあり、仕様が変更される可能性があります[2, 60]。導入にあたってはGitHub Docsの現行版を参照し、ポリシー既定値や認証要件、例外手順の最新情報を確認することが適切です[60]。

後輩最低パッケージ年齢を厳しく設定しすぎると、緊急のセキュリティパッチが出たときにもブロックされてしまいますね。

先輩その通りだね。だからこそ、ログに表示されるURLから即座に申請を出して承認者が解除できる例外フローが用意されているんだよ。

後輩開発の速度と安全性のバランスを取りながら、組織ごとの運用ポリシーに合わせて調整していくのがポイントなんですね。