mcpField
D
detecting-typosquatting-packages

detecting-typosquatting-packages

github.com/mukul975セキュリティ35.2k41 回インストール8 週間前に更新
リポジトリ

detecting-typosquatting-packages について

ソフトウェアサプライチェーンを守るため、インストール前にパッケージ名を調べるセキュリティスキルです。名前の変異照合、リスク評価、CI/CD への組み込みを扱います。

主な機能

  1. 01人気パッケージ名との照合
  2. 02一般的な名前の変異生成
  3. 03レジストリ情報によるリスク評価
  4. 04CI/CD ゲートへの組み込み
  5. 05既知の偽装パッケージデータの参照

活用シーン

  1. 01依存関係に追加する前の名前確認
  2. 02AI 生成やチュートリアル由来の依存関係の確認
  3. 03プルリクエストで新規依存関係を検査
  4. 04ロックファイル変更に含まれる疑わしい名前の調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill detecting-typosquatting-packages

インストール後、Claude Code で/detecting-typosquatting-packagesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE
references/
api-reference.md
standards.md
scripts/
agent.py

詳細

typosquatting パッケージの検出

認可された用途のみ: このスキルは、防御的なソフトウェアサプライチェーンのセキュリティ、パッケージのスクリーニング、および認可を受けた調査を目的としています。ここで説明するコーパスマッチングとレジストリクエリの手法は、大規模な照会が許可されているレジストリに対して、また自組織で評価する意図のあるパッケージに対してのみ使用してください。大量の自動化されたレジストリスクレイピングは、レジストリの利用規約に違反する可能性があります。

概要

Typosquatting は、ソフトウェアサプライチェーン攻撃(MITRE ATT&CK T1195.002 — Supply Chain Compromise: Compromise Software Supply Chain)です。攻撃者は、人気のある正規パッケージに名前がよく似た悪意のあるパッケージを公開します。例として、requests に対する reqeusts、sqlite3 に対する python-sqlite、cross-env に対する crossenv があります。開発者がタイプミスで名前を誤入力したり、汚染されたチュートリアルから名前をコピーしたり、AI が生成した依存関係リストを信頼したりすると(「slopsquatting」と呼ばれる亜種です。モデルが存在しないパッケージ名を幻覚し、攻撃者がそれを登録します)、正規のパッケージではなく squat パッケージをインストールしてしまいます。多くのエコシステムではインストール時スクリプト(npm の postinstall、PyPI の setup.py/ビルドフック)が実行されるため、ペイロードは開発者の権限で即座に実行されます。

このスキルでは、インストール前に行う能動的な検出を扱います。攻撃者が使うのと同じ名前変異のプリミティブを用いて、候補パッケージ名を人気のある既知の正規名のコーパスと照合し、リスクの高いマッチをトリアージします。代表的なオープンソースの検出ツールは typomania(Rust Foundation)です。これは学術ツール typogard(「Defending Against Package Typosquatting」、カンザス大学)の Rust 移植版で、crates.io のライブ typosquatting チェックを支えています。エコシステムを横断するカバレッジは、Microsoft OSSGadget の oss-find-squats と、PyPI 向けの IQTLabs pypi-scan から得られます。ecosyste-ms の typosquatting-dataset は、既知の squat と正規の対象との対応を示す、キュレーションされた正解データのコーパスを提供します。

出典: Rust Foundation typomania(https://github.com/rustfoundation/typomania)、Microsoft OSSGadget、ecosyste-ms typosquatting-dataset、および OWASP CI/CD / SLSA のサプライチェーンガイダンス。

使用するタイミング

  • package.json、requirements.txt、pyproject.toml、Cargo.toml に新しい依存関係を追加する前
  • プルリクエストで新しく導入されたすべての依存関係名をスクリーニングする CI/CD ゲートとして
  • AI が生成した、またはチュートリアル由来の依存関係リストをトリアージするとき(「slopsquatting」レビュー)
  • ロックファイルの差分をセキュリティレビューする際に、入れ替えられた squat や新たにピン留めされた squat を見つけるとき
  • 疑わしい squat のインストールをブロックするレジストリ側またはプロキシ側のガードレールを構築するとき

前提条件

  • typomania をビルド・使用するための Rust ツールチェーン(cargo)、または OSSGadget のビルド済みリリース
  • pypi-scan とこのスキルのヘルパースクリプトのための Python 3.8 以上
  • 対象レジストリの公開 API(npmjs.org、pypi.org、crates.io)へのネットワークアクセス
  • エコシステムの「人気のある」パッケージ名のコーパス(ダウンロード数または上位 N 件のリスト)

ツールをインストールします:

# typomania (library + example harness) — Rust Foundation
git clone https://github.com/rustfoundation/typomania
cd typomania
cargo build --release
cargo run --example registry   # demonstrates the Harness against a fake registry

# OSSGadget (Microsoft) — cross-ecosystem squat finder
# Download a release binary, then:
oss-find-squats pkg:npm/requests          # purl syntax
oss-find-squats pkg:pypi/reqeusts

# pypi-scan (IQTLabs) — PyPI typosquat enumerator
git clone https://github.com/IQTLabs/pypi-scan
cd pypi-scan
pip install -r requirements.txt

# ecosyste-ms ground-truth dataset of known squats
git clone https://github.com/ecosyste-ms/typosquatting-dataset

目的

  • 標準的な変異プリミティブを用いて、特定の正規名に対する候補 squat の集合を生成する
  • 候補パッケージ名を人気のある名前のコーパスと照合し、類似度の高いものを検出する
  • 疑わしい各 squat をレジストリのメタデータ(作成からの経過期間、ダウンロード数、メンテナー、インストールスクリプト)で補強する
  • 検出結果をスコア付けしてトリアージし、誤検知(正当なフォークやスコープ付きパッケージ)を抑制する
  • チェックを CI/CD に組み込み、新しい依存関係をブロックするゲートとして機能させる

MITRE ATT&CK マッピング

Technique IDNameTactic
T1195.002サプライチェーンの侵害: ソフトウェアサプライチェーンの侵害初期アクセス

typosquat された依存関係は T1195.002 の配送手段となります。攻撃者は正規のパッケージを侵害するのではなく、悪意のある酷似パッケージを代わりにインストールさせることで、被害者のサプライチェーンを侵害します。関連する後続の挙動として、インストールフックによる T1059(コマンドおよびスクリプトインタプリタ)や、トークンおよび環境変数の窃取による T1041/T1567(流出)が頻繁に見られます。

ワークフロー

Step 1: 人気パッケージ名のコーパスを構築する

検出器には、比較対象となる正当な名前の参照セットが必要です。エコシステムごとにダウンロード数の多い上位パッケージを取得します。

# PyPI: top packages dataset (Hugo van Kemenade's top-pypi-packages)
curl -s https://hugovk.github.io/top-pypi-packages/top-pypi-packages.min.json \
  -o top-pypi-packages.json

# npm: query the registry's most-depended-upon search
curl -s 'https://registry.npmjs.org/-/v1/search?text=not:unstable&popularity=1.0&size=250' \
  -o npm-top.json

# crates.io: top crates by downloads
curl -s 'https://crates.io/api/v1/crates?sort=downloads&per_page=100' \
  -H 'User-Agent: typosquat-screen ([email protected])' -o crates-top.json
Step 2: 標準的な変異プリミティブで候補となるスクワッティング名を生成する

typomania/typogard は、実際の攻撃者の振る舞いを反映した一連の名前変換を固定的に適用します。スクリーニングで何を検出すべきかを理解するために、これらを再現します:

1. Repeated characters     requests  -> reqquests
2. Omitted characters      requests  -> requsts
3. Swapped/transposed      requests  -> reqeusts
4. Swapped words           python-dateutil -> dateutil-python
5. Common typos (1-edit)   requests  -> rewuests   (keyboard adjacency)
6. Homophones / vowel swap requests  -> requeasts
7. Version / suffix tricks lodash    -> lodashs, lodash-js
8. Delimiter swaps         cross-env -> crossenv, cross_env
9. Scope confusion (npm)   @types/node -> types-node

typomania のハーネスを実行します。これは Corpus と Harness トレイトの背後で、これらを再利用可能なプリミティブとして実装しています:

# In the typomania checkout: feed your popular corpus, then check a name.
# The Harness::check method (parallelized via rayon) compares the candidate
# against every corpus entry using the squatting primitives.
cargo run --example registry -- --corpus top-pypi-packages.json --name reqeusts
Step 3: OSSGadget oss-find-squats でスクリーニングする

OSSGadget はライブレジストリに問い合わせ、指定されたパッケージの変異名を生成し、そのうちどの変異名が実際に公開パッケージとして存在するかを報告します。

# Find names that squat on a legitimate package, checking which exist in the registry
oss-find-squats pkg:npm/lodash
oss-find-squats pkg:pypi/requests

# Reverse direction: given a SUSPECT name, find the legitimate package it mimics
oss-find-squats --quiet pkg:npm/loadsh
Step 4: pypi-scan で PyPI のスクワッティングを列挙する
cd pypi-scan
# Find candidate typosquats of a specific package
python pypi_scan.py -p requests

# Scan the top-N most-downloaded PyPI packages for existing squats
python pypi_scan.py -n 50
Step 5: レジストリのメタデータで疑わしいスクワッティング候補を補強する

名前が少し似ているだけでは、疑わしいとは言えません。新しい、ダウンロード数が少ない、またはインストールスクリプトを含む場合に初めて疑わしくなります。メタデータを取得してトリアージします:

# npm package metadata: creation time, maintainers, scripts
curl -s https://registry.npmjs.org/loadsh | \
  python -c 'import sys,json;d=json.load(sys.stdin);v=d["dist-tags"]["latest"];print("created:",d["time"]["created"]);print("scripts:",d["versions"][v].get("scripts",{}))'

# npm download counts (last week)
curl -s https://api.npmjs.org/downloads/point/last-week/loadsh

# PyPI JSON API: release history and author
curl -s https://pypi.org/pypi/reqeusts/json | \
  python -c 'import sys,json;d=json.load(sys.stdin);i=d["info"];print(i["name"],i["author"],i["home_page"]);print("releases:",list(d["releases"].keys()))'
Step 6: スコアリング、トリアージ、確認を行う

シグナルを組み合わせてリスクスコアを算出します。高リスク = 人気名との編集距離が小さい AND(パッケージの公開から90日未満 OR ダウンロード数 < 1000 OR postinstall/preinstall/セットアップ時のネットワーク呼び出しが存在する)。ecosyste-ms の既知スクワッティングデータセットと照合します:

# Is this name a documented squat?
grep -i 'loadsh' typosquatting-dataset/data/*.csv

悪意の有無は、(サンドボックスまたは VM 内でのみ)インストールスクリプトとソースの tarball を調べて確認します。疑わしいパッケージを、ワークステーション上で npm install や pip install してはいけません。

Step 7: CI/CD で強制する

PR で導入される新しい依存関係名をすべてスクリーニングするブロッキングゲートを追加します:

# .github/workflows/typosquat-gate.yml
name: typosquat-gate
on: [pull_request]
jobs:
  screen:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Screen new dependencies
        run: |
          git diff origin/${{ github.base_ref }}...HEAD -- package.json requirements.txt \
            | grep '^+' | python scripts/agent.py screen --ecosystem npm --corpus top.json --stdin

ツールとリソース

ToolPurposeSource
typomaniaRust typosquat-detection library (powers crates.io)https://github.com/rustfoundation/typomania
OSSGadget oss-find-squatsCross-ecosystem squat finder (purl)https://github.com/microsoft/OSSGadget
pypi-scanPyPI typosquat enumeratorhttps://github.com/IQTLabs/pypi-scan
ecosyste-ms typosquatting-datasetCurated known-squat ground truthhttps://github.com/ecosyste-ms/typosquatting-dataset
top-pypi-packagesPyPI popular-name corpushttps://hugovk.github.io/top-pypi-packages/
OWASP CI/CD Security Top 10Supply-chain control guidancehttps://owasp.org/www-project-top-10-ci-cd-security-risks/

変異プリミティブのリファレンス

PrimitiveLegitSquatWhy it works
TranspositionrequestsreqeustsCommon typing slip
OmissionrequestsrequstsDropped character
RepetitionrequestsreqquestsStuck key
Delimiter swapcross-envcrossenvHyphen vs none ambiguity
Word orderpython-dateutildateutil-pythonReordered compound name
Homoglyph/vowelrequestsrequeastsVisual/phonetic similarity
Suffix/scopelodashlodash-js, loadshPlausible "official" variant

検証基準

  • 対象となる各エコシステムについて、人気名のコーパスをダウンロードした
  • 変異プリミティブを再現し、既知のスクワッティング名(例: loadsh)が正しくフラグされることを確認した
  • typomania / OSSGadget / pypi-scan を、少なくとも1つの実際のパッケージに対して実行した
  • 疑わしいスクワッティング候補を、公開からの期間、ダウンロード数、インストールスクリプトのメタデータで補強した
  • 検出結果を ecosyste-ms の既知スクワッティングデータセットと照合した
  • リスクスコアリングにより、明らかな誤検出(正当なスコープ付きパッケージやフォークしたパッケージ)が抑制されている
  • CI/CD ゲートが、すべてのプルリクエストで新しい依存関係名をスクリーニングしている
  • 疑わしいパッケージを、使い捨てのサンドボックス外にインストールしていない

コメント