インストールは、コードを実行する入口です
依存パッケージは、インストール、ビルド、テスト、通常のimportなどでコードを実行します。確認したいのは、どのコードが動き、どの認証情報・ファイル・通信先・公開権限に届くかです。
公開後7日間は導入を待つ設定にすると、混入直後の不正な版を取り込む可能性を下げられます。ただし、古いパッケージの安全性や、侵害済みrunnerの復旧までは保証しません。本記事は2026年10月23日に確認した、pnpm 11.19で利用できる設定を扱います。例と演習は設計用であり、読者の環境で検証済みという意味ではありません。
待機期間をworkspaceに設定する
pnpm 11.19のworkspaceでは、rootのpnpm-workspace.yamlに次を設定します。
minimumReleaseAge: 10080
minimumReleaseAgeStrict: true
minimumReleaseAgeIgnoreMissingTime: false
trustLockfile: false
blockExoticSubdeps: true
strictDepBuilds: true
trustPolicy: no-downgrade10080は分単位で7日です。直接依存と推移依存の両方に適用します。条件を満たす版がない場合や公開日時が欠ける場合も、上の設定では失敗します。trustLockfile: falseは既存entryにも年齢・信頼検査を適用し直します。一方、--frozen-lockfileの役割はlockfileの書き換え禁止です。no-downgradeは公開来歴の信頼度低下を検査しますが、プログラムの振る舞いを検査する機能ではありません。正確な契約と対応版はpnpm公式の依存解決設定で確認できます。
packageManagerには正確な版を指定し、そのpnpmを取得する手順も確認します。別のnpmやpip、Docker pull、ダウンロードしたshell scriptには、workspaceの設定が自動で適用されるわけではありません。ローカルのsetup、CI、deploy script、ドキュメントに別経路が残っていないか調べます。
待機の例外をscope全体へ広げるのは避けます。新しすぎる修正版は更新待ちとし、確認済みの対象版や機能停止などで対処します。その結果、到達可能な脆弱性が残るなら、残る影響と具体的な緩和策を記録して判断します。黙って新しい版を通すと待機設定が無意味になり、脆弱な版を黙って残すとセキュリティ改善になりません。
必要なinstall scriptだけを許可する
公開日時の条件を満たすことと、そのパッケージのinstall scriptを実行してよいことは別の判断です。allowBuildsで確認済みの対象を許可し、strictDepBuilds: trueで未審査のscriptがあるインストールを失敗させます。版まで指定すると許可を狭められます。
# 設定の形を示す例。確認済みのpackageとversionへ置き換えてください。
allowBuilds:
"your-reviewed-native-addon@1.2.3": trueこれは推奨パッケージではなく、形式を示すplaceholderです。そのまま動く許可リストとして使わないでください。版なしの許可は後続版にも及びます。全scriptの一括許可は、今後追加される推移依存のscriptにも及びます。一方、すべて拒否するとnative toolが動かなくなる場合があるため、実際のscriptを読み、必要性を判断します。仕様はpnpmのbuild設定にあります。
この制御が減らすのは、実行経路の一部です。テストや本番でimportした不正moduleも動き得ます。scriptを確認した後も、install・test jobから公開用credentialを分離します。
差分を確認してから更新する
まず現在の依存グラフとadvisoryを確認します。公開から7日以上経ったstable版のうち、問題を修正する互換patch・minorを優先します。修正が次majorにしかないなら、移行を明示的に検証します。「元のmajorの最新版」は脆弱性修正の証拠になりません。
manifestとlockfileは一緒に確認します。推移依存の追加、確認できる公開元の変化、integrityの変更、git/tarball依存、install script、overrideを見ます。直接依存の小さな版変更でも、実行される依存グラフが大きく変わることがあります。
検証の流れは次のようになります。
pnpm install --frozen-lockfile
pnpm audit
# 続けて、影響するアプリのcheck・test・buildを実行します。固定したpackage managerを使い、本番の秘密を渡さない隔離環境で実行します。registryへ接続できない状態は監査未完了です。公開後日数の検査で失敗したら、対象版と公開日時を確認します。検査を無効にして成功へ変えないようにします。
CIの入力に、公開権限を引き継がせない
2025年のNx s1ngularity事後報告には、非信頼PRのtitleから特権workflowへ入り、不正な公開につながった経路が記録されています。最初のjobだけでなく、その後のjobまで入力・コード実行・credentialのつながりを追う必要があります。
確認済みのActionはfull commit SHAに固定し、内部で呼ぶ依存も確認します。jobの権限を必要最小限にし、非信頼PRの実行とdeploy・publish credentialを受け取るjobを分離します。非信頼jobが作るartifactやcacheも、特権jobが使うときは非信頼の入力です。PR titleを環境変数経由で扱えば直接のshell展開を避けられますが、PRのコードを公開token付きで動かしてよいことにはなりません。
PyPIによる2024年12月のUltralytics分析は、CI cacheの操作を通じた不正公開と、後に古い公開tokenが使われた経緯を説明しています。Trusted Publishingは公開したworkflowを示す仕組みですが、workflowと入力が侵害されていない証明にはなりません。来歴検証に加え、旧credentialの廃止とrelease用cacheの分離が必要です。
2026年10月21日のLiteLLM公式報告では、不正な1.107.0配布物がPyPIとDockerへ入り、通常のソースtagには不正ファイルがなかったとしています。本記事の確認時点でも調査は継続中です。ソースtagやstableというimage名だけで判断せず、実際の配布物とinstallerごとの経路を確かめる材料になります。
設定を、観測できる結果にする
使い捨てのprojectや管理下のregistry fixtureで確かめます。以下は試験計画であり、読者の基盤に対して実行した結果ではありません。
| 管理下で作る条件 | 期待する結果 |
|---|---|
| 公開から7日を超えたstable版 | 他の条件も通れば導入できる |
| 公開1日後の直接依存 | インストール失敗 |
| 公開1日後の推移依存 | インストール失敗 |
| lockfile内の既存entryが新しすぎる | frozen installでも年齢検査に失敗 |
| registryが公開日時を返さない | 明示的な失敗 |
| 未審査install scriptを追加する依存 | そのscriptを実行せず失敗 |
| 許可されないPRがrelease credentialへ到達を試みる | credentialを取得できずreleaseも開始できない |
終了コードと、禁止した副作用が起きていないことの両方を確認します。scriptのfixtureには使い捨てdirectoryへ無害なmarker fileを作る処理を使い、そのfileがないことを検査できます。本番の依存へfixtureを入れる必要はありません。
AIエージェントへ監査を依頼するなら、次の短い指示を使えます。
manifest、lockfile、install script、CI event、artifact、cache、deploy権限を追ってください。到達可能なリスクごとに、攻撃者が制御する入力、実行箇所、credentialまたは副作用、成立条件を示してください。無害なローカルデータで再現し、境界を修正して、拒否と正常系を検証してください。監査失敗と未実行の確認は明示してください。
不正なpackageを既に実行した場合、版の変更だけでは復旧を完了できません。実行したartifactを特定し、環境を隔離し、到達できたcredentialを失効させ、清浄な素材から再構築します。侵害されたrunnerやcacheを消す前に、影響範囲の判断に必要な証拠を機微情報を除いて保全し、事故対応主体の案内に従います。
MENTAL MODEL / 考える順序
発表から、自分の判断へ。
発表の主張と、論文・公式ドキュメントの条件を並べて読む。
出典
公開日は資料の日付、確認日は内容を参照した日です。コミュニティの観測は公式の確定事項と区別します。
01