[{"data":1,"prerenderedAt":277},["ShallowReactive",2],{"content-/npm-supply-chain-defense":3,"all-pages-for-dir":275,"og-image-/npm-supply-chain-defense":276},{"id":4,"title":5,"body":6,"category":255,"description":256,"extension":257,"meta":258,"navigation":259,"path":260,"project_name":261,"published":262,"publishedAt":263,"seo":264,"stem":265,"tags":266,"todo":272,"updatedAt":273,"__hash__":274},"pages/2026-04/2026-04-03/npm-supply-chain-defense.md","npmサプライチェーン攻撃 Shai-Hulud 2.0 への防御設定 - minimum-release-ageで新規バージョンをブロック",{"type":7,"value":8,"toc":249},"minimark",[9,14,23,26,29,34,37,56,59,61,65,72,75,98,100,103,110,191,198,214,216,219,245],[10,11,13],"h1",{"id":12},"npmサプライチェーン攻撃-shai-hulud-20-への防御設定","npmサプライチェーン攻撃 Shai-Hulud 2.0 への防御設定",[15,16,17,18,22],"p",{},"claude-code-syncのログを眺めていたら「Shai-Hulud 2.0」という名前が目に飛び込んできた。npm史上最悪のサプライチェーン攻撃だという。正規パッケージのメンテナー認証情報を盗み取り、そのまま悪意あるバージョンをnpmに公開する手口で、",[19,20,21],"code",{},"npm audit"," では検出できない。正規パッケージが汚染されるので、依存関係のハッシュだけ見ていても気づけない。",[15,24,25],{},"手が止まった。自分のプロジェクトは大丈夫なのか、すぐに確認を始めた。",[27,28],"hr",{},[30,31,33],"h2",{"id":32},"影響チェック-感染の兆候なし","影響チェック: 感染の兆候なし",[15,35,36],{},"複数のチェックを並行で走らせた。",[38,39,40,47,53],"ul",{},[41,42,43,46],"li",{},[19,44,45],{},"pnpm audit"," で既知の脆弱性をスキャン",[41,48,49,52],{},[19,50,51],{},"pnpm-lock.yaml"," の最近の変更差分を確認（意図しないバージョン変更がないか）",[41,54,55],{},"依存パッケージの公開日時を確認（直近24時間以内に公開されたバージョンがないか）",[15,57,58],{},"結果、感染の兆候は見つからなかった。ひとまず安心したが、攻撃の手口を考えると「今回たまたま踏まなかっただけ」にすぎない。次の波が来る前に防御を張ることにした。",[27,60],{},[30,62,64],{"id":63},"防御設定-minimum-release-age","防御設定: minimum-release-age",[15,66,67,68,71],{},"pnpmには ",[19,69,70],{},"minimum-release-age"," という設定がある。npmレジストリに公開されてから指定時間が経過していないバージョンのインストールをブロックする。公開直後に仕込まれた悪意あるバージョンは、コミュニティが異変に気づいて取り下げられるまでに数時間〜数日かかる。その「空白の時間」にインストールしないようにするのが狙いだ。",[15,73,74],{},"3日（4320分）を設定した。",[76,77,82],"pre",{"className":78,"code":79,"language":80,"meta":81,"style":81},"language-ini shiki shiki-themes vitesse-light vitesse-light","# ~/.npmrc\nminimum-release-age=4320\n","ini","",[19,83,84,92],{"__ignoreMap":81},[85,86,89],"span",{"class":87,"line":88},"line",1,[85,90,91],{},"# ~/.npmrc\n",[85,93,95],{"class":87,"line":94},2,[85,96,97],{},"minimum-release-age=4320\n",[27,99],{},[30,101,102],{"id":102},"設定の置き場所を変えた",[15,104,105,106,109],{},"最初は ",[19,107,108],{},"pnpm-workspace.yaml"," に書いた。",[76,111,115],{"className":112,"code":113,"language":114,"meta":81,"style":81},"language-yaml shiki shiki-themes vitesse-light vitesse-light","# pnpm-workspace.yaml（最初の設定 → 削除済み）\npackages:\n  - \"apps/*\"\nonlyBuiltDependencies:\n  - \"@libsql/linux-x64-gnu\"\n  - ...\nminimumReleaseAge: 4320\n","yaml",[19,116,117,123,133,150,158,170,179],{"__ignoreMap":81},[85,118,119],{"class":87,"line":88},[85,120,122],{"class":121},"sxvE3","# pnpm-workspace.yaml（最初の設定 → 削除済み）\n",[85,124,125,129],{"class":87,"line":94},[85,126,128],{"class":127},"sz8Xr","packages",[85,130,132],{"class":131},"shFtX",":\n",[85,134,136,139,143,147],{"class":87,"line":135},3,[85,137,138],{"class":131},"  -",[85,140,142],{"class":141},"sMJiu"," \"",[85,144,146],{"class":145},"sdGka","apps/*",[85,148,149],{"class":141},"\"\n",[85,151,153,156],{"class":87,"line":152},4,[85,154,155],{"class":127},"onlyBuiltDependencies",[85,157,132],{"class":131},[85,159,161,163,165,168],{"class":87,"line":160},5,[85,162,138],{"class":131},[85,164,142],{"class":141},[85,166,167],{"class":145},"@libsql/linux-x64-gnu",[85,169,149],{"class":141},[85,171,173,175],{"class":87,"line":172},6,[85,174,138],{"class":131},[85,176,178],{"class":177},"sM54T"," ...\n",[85,180,182,185,188],{"class":87,"line":181},7,[85,183,184],{"class":127},"minimumReleaseAge",[85,186,187],{"class":131},":",[85,189,190],{"class":177}," 4320\n",[15,192,193,194,197],{},"動作は確認できたが、これだとこのモノレポでしか効かない。ほかのプロジェクトで ",[19,195,196],{},"pnpm install"," したときは素通しになる。",[15,199,200,201,204,205,207,208,210,211,213],{},"全プロジェクトで効かせるため、",[19,202,203],{},"~/.npmrc"," に移動した。グローバル設定なので、どのディレクトリで ",[19,206,196],{}," を叩いても3日ルールが適用される。プロジェクトレベルの ",[19,209,108],{}," からは ",[19,212,184],{}," の行を削除して重複を消した。",[27,215],{},[30,217,218],{"id":218},"まとめ",[38,220,221,227,230,239,242],{},[41,222,223,224,226],{},"Shai-Hulud 2.0 は正規パッケージのメンテナー認証情報を盗んで悪意あるバージョンを公開する攻撃。",[19,225,21],{}," では検出できない",[41,228,229],{},"プロジェクトの影響チェックを実施し、感染の兆候なしを確認",[41,231,232,235,236,238],{},[19,233,234],{},"minimum-release-age=4320","（3日）を ",[19,237,203],{}," にグローバル設定",[41,240,241],{},"公開から3日以内のバージョンは全プロジェクトでブロックされる",[41,243,244],{},"完全な防御ではないが、「公開直後の汚染バージョンを踏む」リスクを減らせる",[246,247,248],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}",{"title":81,"searchDepth":94,"depth":94,"links":250},[251,252,253,254],{"id":32,"depth":94,"text":33},{"id":63,"depth":94,"text":64},{"id":102,"depth":94,"text":102},{"id":218,"depth":94,"text":218},"dev","npm史上最悪のサプライチェーン攻撃Shai-Hulud 2.0の情報を受け、プロジェクトの影響チェックを実施。感染の兆候なしを確認後、minimum-release-age=4320をグローバル設定して全プロジェクトで公開3日以内のパッケージをブロックした","md",{},true,"/npm-supply-chain-defense","eurekapu-nuxt4",false,"2026-04-03T00:00:00.000Z",{"title":5,"description":256},"2026-04/2026-04-03/npm-supply-chain-defense",[267,268,269,270,271],"npm","サプライチェーン攻撃","セキュリティ","pnpm","npmrc","memo",null,"do9NfHQs5qzye-xzCtGoUtbPEpXEinri9-mRSrB25TM",[],"https://log.eurekapu.com/favicon.svg",1775338204308]