关于 detecting-typosquatting-packages
用于软件供应链防御的技能,指导安全团队在安装前筛查疑似仿冒包,并将检查纳入 CI/CD。内容涵盖名称变体检测、风险核查和结果分级。
主要功能
- 01对照热门包名筛查近似名称
- 02生成常见拼写变体
- 03结合注册表元数据评估风险
- 04将检查纳入 CI/CD 门禁
- 05参考已知仿冒包数据集
适用场景
- 01添加依赖前检查包名
- 02审查 AI 生成或教程提供的依赖
- 03在拉取请求中拦截新依赖风险
- 04排查锁文件中的可疑包名
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill detecting-typosquatting-packages安装后在 Claude Code 中输入/detecting-typosquatting-packages确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdstandards.mdscripts/agent.py详细介绍
检测域名仿冒包
仅限授权使用: 本技能用于防御性软件供应链安全、包筛查和授权研究。仅针对你有权大规模查询的注册表以及你打算为自己组织评估的包,使用本文中的语料库匹配和注册表查询技术。大规模自动抓取注册表可能违反注册表的服务条款。
概述
域名仿冒(Typosquatting)是一种软件供应链攻击(MITRE ATT&CK T1195.002 — 供应链妥协:破坏软件供应链),其中攻击者发布一个恶意包,其名称与流行的合法包极为相似——用 reqeusts 冒充 requests,用 python-sqlite 冒充 sqlite3,用 crossenv 冒充 cross-env。开发者如果打错名称、从被投毒的教程中复制名称,或信任 AI 生成的依赖列表(即 "slopsquatting" 变体,模型幻觉出包名,攻击者随后注册这些名称),就会安装这个仿冒包。由于大多数生态系统会执行安装时脚本(npm 中的 postinstall,PyPI 中的 setup.py/构建钩子),恶意载荷会立即以开发者的权限运行。
本技能涵盖主动的、安装前检测:使用攻击者所用的相同名称变异原语,将候选包名与流行/已知良好名称的语料库进行筛查,然后对高风险匹配进行分诊。典型的开源检测器是 typomania(Rust Foundation),它是学术工具 typogard("Defending Against Package Typosquatting",堪萨斯大学)的 Rust 移植版;typomania 为 crates.io 的实时域名仿冒检查提供支持。跨生态系统的覆盖来自 Microsoft OSSGadget 的 oss-find-squats,对于 PyPI 则来自 IQTLabs pypi-scan。ecosyste-ms 的 typosquatting-dataset 提供了已知仿冒包映射到其合法目标的精选地面真值语料库。
来源: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" 审查)
- 在安全审查锁文件差异时,以捕获被替换或新固定的仿冒包
- 在构建注册表侧或代理侧的防护栏以阻止安装可疑仿冒包时
前置条件
- Rust 工具链(
cargo)用于构建/使用 typomania,或使用预构建的 OSSGadget 发行版 - Python 3.8+ 用于 pypi-scan 和本技能中的辅助脚本
- 对目标注册表公共 API(npmjs.org、pypi.org、crates.io)的网络访问
- 用于该生态系统的"流行"包名语料库(下载量或 top-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
目标
- 使用标准变异原语为给定的合法名称生成候选仿冒包集合
- 将候选包名与流行名称语料库进行筛查并标记近似匹配
- 为每个可疑仿冒包补充注册表元数据(年龄、下载量、维护者、安装脚本)
- 对发现结果进行评分和分诊,以抑制误报(合法分支、作用域包)
- 将检查接入 CI/CD,作为新依赖的阻断门禁
MITRE ATT&CK 映射
| 技术 ID | 名称 | 战术 |
|---|---|---|
| T1195.002 | 供应链妥协:破坏软件供应链 | 初始访问 |
域名仿冒的依赖是 T1195.002 的投递载体:攻击者不是通过入侵真实包来破坏受害者的供应链,而是让恶意仿冒包被安装在其位置。相关的下游行为通常包括通过安装钩子执行的 T1059(命令和脚本解释器)以及令牌和环境变量的 T1041/T1567(数据渗出)。
工作流
第 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
第 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 trait 背后的可复用原语:
# 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
第 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
第 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
第 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()))'
第 6 步:评分、分诊与确认
将信号组合成风险评分。高风险 = 与热门名称的编辑距离小,且(包年龄 < 90 天或下载量 < 1000 或存在 postinstall/preinstall/安装时网络调用)。与 ecosyste-ms 已知抢注数据集交叉核对:
# Is this name a documented squat?
grep -i 'loadsh' typosquatting-dataset/data/*.csv
通过检查安装脚本和源码 tarball(仅在沙箱/虚拟机中)来确认恶意意图——绝不要在工作站上对可疑包执行 npm install 或 pip install。
第 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
工具与资源
| 工具 | 用途 | 来源 |
|---|---|---|
| typomania | Rust 抢注检测库(为 crates.io 提供支持) | https://github.com/rustfoundation/typomania |
OSSGadget oss-find-squats | 跨生态系统抢注查找器(purl) | https://github.com/microsoft/OSSGadget |
| pypi-scan | PyPI 抢注枚举器 | https://github.com/IQTLabs/pypi-scan |
| ecosyste-ms typosquatting-dataset | 精选的已知抢注真值 | https://github.com/ecosyste-ms/typosquatting-dataset |
| top-pypi-packages | PyPI 热门名称语料库 | https://hugovk.github.io/top-pypi-packages/ |
| OWASP CI/CD Security Top 10 | 供应链控制指南 | https://owasp.org/www-project-top-10-ci-cd-security-risks/ |
变异原语参考
| 原语 | 合法 | 抢注 | 为何有效 |
|---|---|---|---|
| 换位 | requests | reqeusts | 常见打字失误 |
| 遗漏 | requests | requsts | 漏掉字符 |
| 重复 | requests | reqquests | 按键卡住 |
| 分隔符替换 | cross-env | crossenv | 连字符与无连字符的歧义 |
| 词序 | python-dateutil | dateutil-python | 复合名称顺序颠倒 |
| 同形字/元音 | requests | requeasts | 视觉/语音相似 |
| 后缀/作用域 | lodash | lodash-js, loadsh | 看似合理的"官方"变体 |
验证标准
- 为每个范围内的生态系统下载热门名称语料库
- 复现变异原语,并正确标记出一个已知抢注(例如
loadsh) - 对至少一个真实包运行 typomania / OSSGadget / pypi-scan
- 用年龄、下载量和安装脚本元数据丰富疑似抢注
- 将发现结果与 ecosyste-ms 已知抢注数据集交叉核对
- 风险评分抑制明显的误报(合法的带作用域/分叉包)
- CI/CD 门禁在每个拉取请求上筛查新依赖名称
- 未在一次性沙箱之外安装任何可疑包