はじめに
開発者のNazar Boyko氏がdev.toで、AIが存在しないパッケージ名を提案し、それを攻撃者が乗っ取る「スロップスクワッティング(Slopsquatting)」について解説しています。本稿では仕組みとnpm・pip・Composer・Goでの違い、実践的な防御策を紹介します。
参考記事
- タイトル: Slopsquatting: The Supply Chain Attack That Weaponizes AI Hallucinations
- 著者: Nazar Boyko
- 発行元: dev.to
- 発行日: 2026年7月
- URL: https://dev.to/nazar-boyko/slopsquatting-the-supply-chain-attack-that-weaponizes-ai-hallucinations-2m2
関連記事



要点
- スロップスクワッティングは、AIコーディングアシスタントが実在しないパッケージ名を提案(ハルシネーション)し、攻撃者がその名前を先回りして登録することで悪意あるコードを配布する攻撃手法である
- USENIX Security 2025の研究では、576,000件のコードサンプルのうち19.7%が実在しないパッケージを推奨しており、そのうち43%は同じプロンプトを繰り返しても毎回再現された
- npmとpipはインストール時にスクリプトを自動実行できるため被害が大きく、Composerはルートパッケージのスクリプトのみ実行、Goにはインストール時実行の仕組み自体が存在しないという違いがある
- ロックファイル・脆弱性スキャナー・タイポスクワッティング検出といった既存の防御策は、いずれも「初めて見る新規パッケージ」を想定していないためすり抜けやすい
- 対策の核心は、AIが提案したパッケージ名を実在確認なしに信頼しないこと、およびインストール時のスクリプト自動実行を既定で無効化することにある
詳細解説
スロップスクワッティングとは何か
タイポスクワッティング(typosquatting)は、開発者の打ち間違いを狙ってexpresのような似た名前のパッケージを登録しておく古典的な攻撃手法です。これに対しスロップスクワッティングは、開発者ではなくAIコーディングアシスタントの誤りを起点とします。dev.toの記事によれば、この用語はPython Software FoundationのDeveloper-in-ResidenceであるSeth Larson氏が名付け、Ecosyste.msのAndrew Nesbitt氏が広めたとされています。
AIが「もっともらしいが実在しないパッケージ名」を提案し、それを見た攻撃者がそのパッケージ名を先回りして公開レジストリに登録します。開発者は名前を正確にコピー&ペーストしているため、タイポは一切発生していません。誤りはすでにモデル側で起きており、人間はそれを忠実に再現しているだけという点が、この攻撃の厄介なところだと考えられます。
なぜ機能するのか:ハルシネーションの頻度と再現性
この攻撃が成立する理由は、AIによるパッケージ名のハルシネーションが「まれ」でも「一回限り」でもないことにあります。dev.toの記事で紹介されているUSENIX Security 2025の研究「We Have a Package for You!」では、16種類のLLMを対象にPythonとJavaScriptで576,000件のコードサンプルを生成し、推奨されたパッケージをすべて検証しました。その結果、 19.7%のパッケージが実在せず 、205,474個の異なる架空パッケージ名が確認されたと報告されています。商用モデルの平均は5.2%程度と比較的低く、オープンソースモデルは21.7%程度と高かったとされています。
さらに重要なのは再現性です。同研究では、架空パッケージを生成した500件のプロンプトをそれぞれ10回ずつ再実行したところ、 43%の架空パッケージ名が毎回まったく同じ名前で再現され 、58%は複数回の実行で再登場したと報告されています。一度も再現しなかったものは39%にとどまりました。この再現性の高さは、攻撃者にとって都合の良い情報だと考えられます。ランダムに大量の名前を登録する必要はなく、繰り返し出現する名前だけを狙って登録すればよいためです。
また、Levenshtein距離(文字列同士の類似度を測る指標)を用いた分析では、架空パッケージ名のうち実在パッケージのタイポと呼べるものはわずか13%で、約半数は実在パッケージとほとんど似ていない、完全な「発明」だったとされています。この「似ていない」という性質が、後述するタイポスクワッティング検出をすり抜ける一因になっていると考えられます。
攻撃の流れと実例
攻撃は次の4段階で進むとされています。
- AIがインポート文を提案する ―— 開発者の要望に合わせて、AIがそれらしい名前のパッケージを提示する。名前は架空だが、命名規則やケーシングはそのエコシステムの慣習に沿っている
- 開発者が名前の見た目を信頼する ―— 名前が自然に見えるため、パッケージ名そのものを疑わずにコードレビューを通してしまう
- インストールがコードを実行する ―— npmのpostinstallフックやpipのsetup.pyビルドなど、インストール処理の一部として任意コードが自動実行される場合がある
- 認証情報が外部に送信される ―— 環境変数、~/.aws/credentials、~/.npmrcのトークン、GITHUB_TOKENなどをペイロードが読み取り、攻撃者のサーバーに送信する
実例として、セキュリティ研究者のBar Lanyado氏(Lasso Security)は、AIが繰り返し提案するhuggingface-cliという架空パッケージに着目し、実験としてPyPI上に空のパッケージを同名で登録しました。dev.toの記事によれば、その後3か月で1万5千件以上のダウンロードが発生し、Alibabaの「GraphTranslator」プロジェクトのREADMEにもpip install huggingface-cliという誤った案内が掲載されていたとされています(実際のツールはpip install -U “huggingface_hub[cli]”でインストールする必要があります)。Lanyado氏のパッケージは意図的に無害でしたが、悪意ある攻撃者であればそうとは限りません。
エコシステムごとの違い(npm・pip・Composer・Go)
同じ「架空パッケージを乗っ取る」という攻撃でも、パッケージマネージャーによって被害の広がり方は異なります。
npmが最も攻撃者に有利 だとされています。preinstall・install・postinstallといったライフサイクルスクリプトがnpm install時に自動実行されるためです。この点を踏まえ、pnpm v10は2025年初頭に依存パッケージのライフサイクルスクリプトを既定で無効化し、npm側も2026年6月にnpm v12でスクリプトの自動実行を既定オフにすると発表しています。
{
"name": "requests-oauth2-helper",
"version": "1.0.3",
"scripts": {
"postinstall": "node ./collect.js"
}
}pipも同様のリスクを抱えます。 ソース配布(sdist)はインストール時にsetup.pyを実行して任意コードを動かせる一方、ホイール(.whl)はインストール時にコードを実行しないため、–only-binaryオプションが有効な防御策になります。
# ソースビルドを拒否し、事前ビルド済みのホイールのみを受け付ける
pip install --only-binary :all: requests-oauth2-helperComposerは設計上比較的安全 とされています。Composerが自動実行するのはルートパッケージのcomposer.jsonに定義されたスクリプトのみで、依存パッケージ自身のスクリプトは無視されます。ただし、インストールイベントにフックできる悪意あるComposerプラグインという例外があるため、信頼できないコードベースではcomposer install –no-plugins –no-scriptsの利用が推奨されています。
Goにはインストール時実行の仕組み自体が存在しません。 go getやgo buildはパッケージ追加の時点で任意コードを実行しないため、悪意あるコードはinit()関数経由でプログラムを初めて実行したとき、あるいはgo test実行時に動き出すことになります。dev.toの記事では、2021年11月にアップロードされた偽装パッケージgithub.com/boltdb-go/boltがGoモジュールプロキシにキャッシュされ、後にGitタグをクリーンなコードへ書き換えたにもかかわらず、プロキシが古い悪意あるバージョンを配信し続け、3年以上発見されなかった事例が紹介されています。ビルドの再現性を担保するためのキャッシュ機構が、汚染されたバージョンを長期間温存してしまう例だと言えます。
既存の防御策が効きにくい理由
従来のサプライチェーン対策の多くは、スロップスクワッティングとは異なる脅威モデルを前提に作られていると考えられます。
ロックファイルは初回インストール後にしか効果を発揮しません。 package-lock.jsonやcomposer.lockはバージョンを固定してくれますが、スロップスクワッティングが狙うのは「まだ一度もインストールしたことのない新しい名前」の初回インストールです。ロックファイルにはまだ何も記録されていません。
脆弱性スキャナーは既知の脅威と照合する仕組みです。 登録されたばかりの架空パッケージにはCVEも履歴もレピュテーションもないため、スキャナーの判定基準に引っかからないと考えられます。
タイポスクワッティング検出は編集距離をもとに似た名前を検出します。 しかし前述の通り、架空パッケージ名の約半数は実在パッケージとほとんど似ていない完全な新規発明であるため、比較対象となる「似た実在パッケージ」自体が存在せず、検出のしようがないという構造的な弱点があります。
実装:今日から使える対策
防御の核心は「AIが提案した名前を検証なしに信頼しない」という基本に立ち返ることだと思います。dev.toの記事で紹介されている具体的な対策を、コマンドとともに整理します。
前提条件: npm・pip・Composerなど、通常利用しているパッケージマネージャーがコマンドラインから使える状態であれば追加のセットアップは不要です。
まず、AIが提案したパッケージをインストールする前に、レジストリ上に実在し、継続的にメンテナンスされているかを確認します。
# npm: パッケージの存在有無、所有者、公開からの経過期間を確認する
npm view requests-oauth2-helper
# PyPI: プロジェクトページやリリース履歴、メンテナーを確認する
pip index versions requests-oauth2-helperこのコマンドが404などで失敗する場合、そのパッケージはAIが作り出した架空の名前である可能性が高いと考えられます。
次に、インストール時のスクリプト自動実行を既定で無効化します。これによりキルチェーンの中で最も静かに実行される攻撃経路を塞ぐことができます。
# npm: ライフサイクルスクリプトを全体で無効化する
npm config set ignore-scripts true
# pnpm v10以降は依存パッケージのスクリプトを既定でブロックする
# 本当に必要なものだけ個別に承認する
pnpm approve-builds
# pip: 事前ビルド済みホイールを優先し、setup.pyの実行を避ける
pip install --only-binary :all: <package>
# Composer: 信頼できないコードベースではプラグインとスクリプトを無効化する
composer install --no-plugins --no-scriptsdev.toの記事では、npmパッケージのうちインストールスクリプトを正当に必要とするものは全体の約2%にとどまるとされており、これが既定オフへと業界が動いている根拠になっていると考えられます。
より組織的な対策としては、プライベートレジストリを経由させ、レビュー済みのパッケージのみを許可する方法があります(Artifactory、Verdaccio、プライベートPyPI、Composerの Satisなど)。この方式では、架空パッケージはインストール後にではなく、そもそも許可リストに載っていないため取得段階で失敗する形になります。
加えて、新しく公開されたバージョンに一定の「様子見期間」を設ける方法も有効だと考えられます。pnpm v11ではminimumReleaseAgeが既定1440分(24時間)に設定されており、公開されたばかりのバージョンをすぐにはインストールしない仕組みが導入されています。攻撃者が新しいハルシネーション名を急いで乗っ取ろうとする動きに対して、この冷却期間は一定の効果があると考えられます。
AIが提案したパッケージ名は、あくまで仮説であり出典ではないと捉えるのがよいのではないでしょうか。見たことのないアカウントによるStack Overflowの回答と同じように、正しいかもしれないが確認するまでは信頼しない、という姿勢が求められているのだと思います。
まとめ
スロップスクワッティングは、AIのハルシネーションを起点とする新しいサプライチェーン攻撃です。ロックファイルやスキャナーだけでは防ぎきれないため、パッケージの実在確認とスクリプト無効化を基本動作にすることが重要だと考えられます。npmサプライチェーン攻撃の事例もあわせてご覧いただければと思います。
