技術 約7分で読めます

npmアカウントaiの7パッケージは週964Mダウンロードでprovenance未設定

いけさん目次

TL;DR

対象 postcssnanoidcaniuse-litebrowserslistautoprefixerpostcss-nestedpostcss-js。DEV Community記事の集計では、npmアカウント ai が公開する7パッケージで週964Mダウンロード、いずれもprovenance未設定

差分 既に悪意あるバージョンが出た話ではない。単一公開者、巨大なダウンロード数、出所証明なしという構造リスクの指摘。issue上では、nanoidnanospy はstaged releasesへ移行済み、PostCSSは1〜2週間で対応予定というメンテナ返答

確認 自分のロックファイルに入っている対象パッケージ、公開直後の更新を即時取り込むCI、npmのprovenance表示、staged releases採用、release-age gate、install script許可制。CSSビルド系とID生成系の両方にまたがるため、直接依存だけでなくビルドツール経由も見る


postcssnanoidbrowserslistcaniuse-liteautoprefixer あたりは、アプリに直接書いた覚えがなくてもロックファイルに入りやすい。
CSSビルド、ブラウザ互換データ、ID生成で広く使われるからだ。

DEV Communityに出た記事では、npmアカウント ai が公開する7パッケージの合計が週964Mダウンロードに達し、どれにもnpm provenance attestation(出所証明の署名情報)が付いていないと指摘している。
これは「汚染版が出た」という報告ではない。
盗まれた公開権限から正規っぽいバージョンが出た場合、利用側がレジストリ上の情報だけで区別しにくい、という話だ。

対象として挙がっているのは次の7つだ。

パッケージDEV記事の週次ダウンロード主な入り方
postcss245,612,332CSS変換の基盤
nanoid206,588,788ID生成
caniuse-lite173,435,668ブラウザ互換データ
browserslist167,746,012対象ブラウザ解決
autoprefixer63,517,741CSS prefix付与
postcss-nested54,486,292ネスト構文変換
postcss-js52,771,544JavaScriptオブジェクト形式のCSS処理

同じ報告者がPostCSSのissueに出した表では、postcss-nested を除いた6パッケージで週869Mと数えている。
どちらの数え方でも、ひとつのアカウントの裏に週8〜9億ダウンロードがぶら下がる構図は変わらない。

問題は単一アカウントと公開経路の見分けにある

npmのtrusted publishingは、CI/CDワークフローからOIDCで公開する仕組みだ。
npm docsは、trusted publishingを使うと長期npmトークンを置かずに公開でき、GitHub ActionsやGitLab CI/CDではprovenance attestationも自動生成されると説明している。

provenanceが付くと、「どの公開リポジトリの、どのワークフローから、どのように作られたパッケージか」を検証しやすくなる。
反対に、ローカル端末や長期トークンから公開されたパッケージでは、正規メンテナの意図した公開なのか、盗まれた認証情報からの公開なのかを外から拾いにくい。

この条件は、前に書いたaxiosのnpm侵害に近い。
axiosでは、正規メンテナのnpmアカウントが侵害され、正規CIではない経路から汚染バージョンが公開された。
パッケージ本体ではなく偽依存 plain-crypto-jspostinstall が動いたので、利用側は npm install の時点で踏んでいた。

今回の ai アカウントでは、そうした悪意あるバージョンが出たわけではない。
ただ、同じ種類の公開権限が非常に大きい範囲を持っている。
CSSビルド系だけでなく、nanoid のようなID生成ライブラリも同じ公開者に集中しているので、1つのアカウント侵害で届く利用範囲が広い。

provenanceは安全判定ではなく公開経路の証拠

provenanceの有無だけで安全判定にはしない。
Mini Shai-HuludのTanStack/Mistral波では、正規GitHub Actions経路が汚染され、SLSA provenance付きの悪意あるnpmパッケージが出た。
直近ではRed Hat系 @redhat-cloud-services を襲ったMiasmaも同じ型で、2026年6月1日に侵害されたGitHub Actions OIDC経路から、32パッケージが有効なSLSA provenance付きで公開された。
provenanceは「そのCIが作った」という事実を示すが、「そのCIのcacheやrunnerが汚染されていない」ことまでは示さない。Red Hatのケースは、provenanceは正しいのにCIがマルウェアをビルドしていた、という状態だった。

逆に、Mastraのeasy-day-js侵害では、個人トークンからの公開でprovenanceが落ちていた。
Mastraの正規リリースはtrusted publisher flowで出ていたため、provenance欠落が正規CI由来ではない差分として使えた。

今回の ai アカウントの話は、後者の検出余地がない状態に近い。
provenanceが常に安全を保証するわけではないが、ない場合は「正規CIではないpublish」を機械的に分ける材料が減る。

メンテナはstaged releasesを選んでいる

PostCSSのGitHub issue #2096では、メンテナのAndrey Sitnik氏(npm・GitHubとも ai)がprovenanceだけでは全てのサプライチェーン攻撃は防げないと返している。
彼の主張は、CIを公開者にすること自体が、2FA付きの手動公開よりむしろ攻撃リスクを上げるというものだ。
TanStackが侵害されたのはCIで公開していてそのトークンが盗まれたからで、CI公開経路を一本足すと、守るべき対象がローカル端末からCIランナーへずれるだけになる、という見立てだ。

その代わりに、staged releasesを追加する方針が示された。
npm docsのstaged publishingは、npm publish で直接公開せず、npm stage publish で一度ステージング領域に置き、メンテナが2FA付きで承認してから公開する仕組みとして説明されている。
trusted publishingと組み合わせる場合も、CIがステージングに投入し、人間が最後に承認する形になる。

2026年6月19日UTCのissueコメントでは、nanoidnanospy は新しいプロセスへ移した、PostCSSは1〜2週間で対応する、とメンテナが書いている。
実際、執筆時点では nanoid@5.1.14 がstaged publishing検出される一方、postcss@8.5.15 はまだ検出されない。
原典記事の時点では7パッケージすべてがprovenanceなしだったが、移行は始まっていて、いまは対象ごとに状態が分かれる段階に入っている。

確認する差分は、provenanceの有無だけに閉じない。

見るもの分かること残るもの
provenance公開経路とビルド元CI自体の汚染
staged releases公開前に人間の2FA承認が入るか承認者端末の侵害、レビュー不足
追加publisherアカウントロック時の復旧経路公開権限の分散管理
release-age gate公開直後の汚染版を取り込むか長く残る汚染版、既存ロックファイル

利用側はロックファイルと公開直後の更新を確認する

利用側で今すぐできる確認は、対象パッケージがどこから入っているかをロックファイルで見ることだ。
直接依存に書いていなくても、Vite、Astro、Tailwind、PostCSS系プラグイン、ブラウザ互換データ更新で入る。

rg '"postcss"|"nanoid"|"caniuse-lite"|"browserslist"|"autoprefixer"|"postcss-nested"|"postcss-js"' package-lock.json pnpm-lock.yaml yarn.lock
npm ls postcss nanoid caniuse-lite browserslist autoprefixer postcss-nested postcss-js

ここで出たから危険、という話ではない。
対象が入っているプロジェクトほど、公開直後の更新をそのままCIへ流すか、数日待つかで挙動が変わる。

pnpm 11とYarn 4.10のrelease-age gateで書いた通り、公開から一定時間が経つまで新しいバージョンを取らない設定は、短時間で削除される汚染版に当たる確率を下げる。
ai アカウントのパッケージ群はダウンロード数が大きいので、公開直後の1時間で入る環境も多い。
CIで毎回fresh installするプロジェクトほど、この設定の差が出る。

install時スクリプトの観点では、今回挙がった全パッケージが同じリスクを持つわけではない。
ただし、過去のaxiosやMastraのように「正規パッケージに依存を1行足し、その依存側の postinstall が動く」形なら、元パッケージが普段install scriptを持つかどうかだけでは拾えない。
npm v12のallowScriptsは、この取得後の自動実行を許可制にする防御になる。

参考