mcpField
D
detecting-typosquatting-packages-in-npm-pypi

detecting-typosquatting-packages-in-npm-pypi

github.com/mukul975安全35.2k136 次安装8 周前更新
代码仓库

关于 detecting-typosquatting-packages-in-npm-pypi

用于检查 npm 和 PyPI 软件包名称仿冒风险的安全技能,适合依赖审计和供应链监控。它生成名称变体、查询注册表,并结合相似度及软件包元数据对候选项评分。

主要功能

  1. 01生成多种名称拼写变体
  2. 02查询 npm 与 PyPI 注册表
  3. 03比较名称相似度和元数据
  4. 04依据多项信号计算风险分
  5. 05输出可疑软件包报告与阻止列表

适用场景

  1. 01审计项目依赖中的近似名称软件包
  2. 02监控组织软件包是否遭仿冒
  3. 03调查疑似拼写错误安装事件
  4. 04评估软件包加入依赖树前的风险

安装

复制下面的命令,在终端中运行。

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

安装后在 Claude Code 中输入/detecting-typosquatting-packages-in-npm-pypi确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

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

详细介绍

检测 npm 和 PyPI 中的域名抢注包

何时使用

  • 审计项目依赖,识别名称与流行库高度相似的包
  • 主动扫描包注册表,查找新发布的、可能是贵组织包域名抢注的包
  • 调查疑似供应链入侵事件,其中开发者安装了拼写错误的包名
  • 构建自动监控,当出现名称接近关键依赖的新包时发出警报
  • 在将不熟悉的包加入项目依赖树之前,评估其风险状况

请勿使用作为判定恶意意图的唯一依据;仅凭名称相似并不能证明包是恶意的。请勿在未人工审核被标记包的情况下用于批量自动下架请求。未经授权请勿用于私有注册表。

前置条件

  • 安装 Python 3.9+ 及 requests 和 python-Levenshtein(或 rapidfuzz)包
  • 能够访问 https://pypi.org/pypi/<package>/json(PyPI JSON API)和 https://registry.npmjs.org/<package>(npm 注册表 API)
  • 一份要监控的流行或关键包列表(例如 PyPI 前 1000 个包、组织的依赖列表)
  • 了解常见的域名抢注模式:字符遗漏、换位、插入、替换以及连字符/下划线操作

工作流

步骤 1:构建目标包监控列表

建立要监控域名抢注的合法包集合:

  • 提取项目依赖:解析 requirements.txt、Pipfile.lock、package.json 或 package-lock.json,提取所有直接和传递依赖名称
  • 包含流行包:从 PyPI 下载量前 1000 的包(可从 https://hugovk.github.io/top-pypi-packages/ 获取)或按下载量排名的 npm 顶级包中补充高价值目标
  • 添加组织包:包含贵组织发布的、攻击者可能通过域名抢注来拦截内部安装的任何包
  • 规范化名称:PyPI 将连字符、下划线和句点视为等价(PEP 503 规范化:re.sub(r"[-_.]+", "-", name).lower())。npm 包名称区分大小写,但作用域包使用 @scope/name 格式。比较前先规范化。
步骤 2:生成候选域名抢注名称

为每个目标包生成可能的域名抢注变体:

  • 字符遗漏:每次移除一个字符(requests -> rquests、requets、reqests)
  • 字符换位:交换相邻字符(requests -> erquests、rqeuests、reques ts)
  • 字符替换:使用 QWERTY 距离映射将字符替换为键盘相邻键(requests -> rrquests、requesta)
  • 字符插入:在每个位置插入常见字符(requests -> rrequests、reqquests)
  • 分隔符操作:对于带连字符的名称,尝试移除、加倍或替换分隔符(my-package -> mypackage、my--package、my_package)
  • 常见前缀/后缀攻击:前置或追加常见字符串(python-requests、requests-python、requests2、requests-lib)
步骤 3:查询注册表 API 以获取候选包

检查生成的候选名称是否确实存在于注册表中:

  • PyPI JSON API:对每个候选包发送 GET https://pypi.org/pypi/<candidate>/json。响应 200 表示该包存在;404 表示不存在。从响应中提取:info.name、info.version、info.author、info.summary、info.home_page、info.project_urls 和 releases(以版本为键,带有 upload_time_iso_8601 时间戳)。
  • npm 注册表 API:发送 GET https://registry.npmjs.org/<candidate>,并带上 Accept: application/json。提取:name、description、dist-tags.latest、time.created、time.modified、maintainers 和 versions。
  • 速率限制:PyPI 没有公开的速率限制,但请遵守合理的请求速率(每秒 1-2 个请求)。npm 注册表在受到速率限制时会返回 429;请实现指数退避。
  • 批量优化:对于大型候选列表,使用连接池(requests.Session)并行化请求,并限制并发数以避免触发滥用防护。
步骤 4:分析包元数据以寻找可疑信号

根据多个启发式信号对每个存在的候选包进行评分:

  • Levenshtein 距离:计算候选名称与目标之间的编辑距离。与热门包距离为 1-2 的包是高优先级嫌疑对象。历史分析显示,40 个已知的域名抢注包中有 18 个与其目标的 Levenshtein 距离为 2 或更小。
  • 发布日期的新近程度:将候选包的首次发布日期与目标包的进行比较。在其近似同名包出现数年后才创建的包更加可疑。标记在过去 90 天内创建、且与数年前发布的包相似的包。
  • 下载量差异:比较每周下载量。合法的相似名称包通常具有相当或可解释的下载量。一个下载量为 50 的包与其下载量为 500 万的近似同名包相比十分可疑。PyPI 下载统计可通过 BigQuery(pypistats.org/api/)获取;npm 在 https://api.npmjs.org/downloads/point/last-week/<package> 提供下载量。
  • 作者和维护者分析:检查候选包的作者是否与合法包的作者匹配。近似相同的名称却有不同的作者会增加可疑度。
  • 描述相似度:比较包描述。域名抢注包经常复制或紧密改写目标包的描述以显得合法。
  • 版本数量:合法包通常随时间推移有许多版本。一个只有 1-2 个版本、且名称与热门包相似的包十分可疑。
  • 仓库 URL 分析:检查候选包是否链接到与目标相同的仓库(可能是合法的复刻/镜像),或者没有仓库 URL(可疑)。
步骤 5:评分、排序并报告发现

将各信号组合成一个综合风险评分,并生成可操作的报告:

  • 加权评分:为每个信号分配权重。示例:Levenshtein 距离 1 = 40 分,Levenshtein 距离 2 = 25 分,创建于 90 天前以内 = 15 分,下载量比率 < 0.001 = 15 分,作者不同 = 10 分,单一版本 = 5 分。总分为 100 分。
  • 阈值分类:得分 >= 70:高风险(很可能是域名抢注),40-69:中风险(需要人工审核),< 40:低风险(很可能是合法的)
  • 生成报告:对于每个被标记的包,包含它所模仿的目标、所有信号值、综合得分、两个包在注册表上的直接链接,以及一项建议(阻止、调查或允许)
  • 可操作的输出:生成一个被标记包名称的阻止列表,可导入到包管理器拒绝列表、CI/CD 策略引擎或制品仓库代理规则中

关键概念

术语定义
域名抢注(Typosquatting)注册一个与热门包名高度相似的包名,利用常见拼写错误诱使开发者安装恶意代码
Levenshtein 距离将一个字符串转换为另一个字符串所需的最少单字符编辑次数(插入、删除、替换);衡量名称相似度的主要指标
依赖混淆(Dependency Confusion)一种更广泛的供应链攻击,攻击者将名称与私有内部包匹配的恶意包发布到公共仓库,利用包管理器解析顺序进行攻击
PEP 503 规范化Python 打包规范,将包名中的连字符、下划线和句点视为等价,即 my-package、my_package 和 my.package 解析为同一个包
QWERTY 距离一种考虑键盘布局的距离度量,衡量标准键盘上两个按键之间的距离,用于检测相邻按键误输入导致的替换
组合抢注(Combosquatting)域名抢注的一种变体,攻击者在包名前或后附加常见词汇(例如 requests-security、python-requests)
StarJacking一种攻击方式,抢注包将其仓库 URL 链接到合法包的 GitHub 仓库,以虚增表面可信度

工具与系统

  • PyPI JSON API:位于 https://pypi.org/pypi/<package>/json 的 REST API,返回包元数据,包括名称、作者、版本、上传时间戳和项目 URL
  • npm Registry API:位于 https://registry.npmjs.org/<package> 的 REST API,返回包元数据,包括维护者、版本历史、创建时间戳和分发信息
  • python-Levenshtein / rapidfuzz:用于快速字符串距离计算的 Python 库,支持 Levenshtein、Damerau-Levenshtein、Jaro-Winkler 及其他相似度指标
  • pypistats.org API:提供 PyPI 包的下载统计数据,可用于比较疑似抢注包与其目标包的下载量
  • npm 下载量 API:位于 https://api.npmjs.org/downloads/point/<period>/<package> 的端点,提供 npm 包的下载统计数据

常见场景

场景:审计 Python 项目中的仿冒名称依赖

背景:一个安全团队发现某位开发者的工作站因安装了一个 Python 包而遭入侵。事件响应团队需要审计所有项目依赖,排查潜在的仿冒名称包,并建立持续监控。

方法:

  1. 解析 requirements.txt 和 Pipfile.lock,提取全部 87 个直接依赖和传递依赖
  2. 针对每个依赖,使用字符遗漏、换位、替换和分隔符操作生成仿冒名称候选,约产生 2,400 个候选名称
  3. 对每个候选名称查询 PyPI JSON API,发现其中 34 个确实作为已发布包存在
  4. 对每个存在的候选进行评分:3 个包得分高于 70(HIGH 风险),其 Levenshtein 距离为 1、创建于最近 60 天内、只有一个版本,且下载量少于 100
  5. 人工复核确认这 3 个中有 2 个是恶意仿冒名称包,其中包含混淆代码,会在安装期间窃取环境变量
  6. 在组织的制品代理中封禁这些恶意包,通过 [email protected] 向 PyPI 报告以请求下架,并将全部 87 个依赖加入持续监控观察列表
  7. 将检测 Agent 实现为每周运行的定时 CI 任务,并在发现新的 HIGH 风险结果时发出告警

陷阱:

  • 在比较前未按 PEP 503 规范化 PyPI 包名,导致连字符与下划线变体之间漏配
  • 将 Levenshtein 距离阈值设得过低(仅为 1),漏掉距离为 2、使用双重替换的仿冒名称包
  • 仅依赖名称相似度而不检查元数据信号,导致对合法相似包名产生高误报率
  • 未考虑 npm 作用域包(@scope/name),其命名规则与非作用域包不同
  • 过于频繁地查询注册表,导致被限流或 IP 被封禁

输出格式

## Typosquatting Detection Report

**Scan Date**: 2026-03-19
**Registry**: PyPI
**Packages Monitored**: 87
**Candidates Generated**: 2,412
**Candidates Found in Registry**: 34
**Flagged as Suspicious**: 5

### HIGH Risk (Score >= 70)

| Suspect Package | Target Package | Levenshtein | Created | Downloads | Score |
|----------------|---------------|-------------|---------|-----------|-------|
| reqeusts       | requests      | 1           | 2026-02-28 | 43     | 92    |
| requsets       | requests      | 1           | 2026-03-01 | 12     | 88    |
| numpyy         | numpy         | 1           | 2026-01-15 | 67     | 78    |

### Recommendation
- BLOCK: reqeusts, requsets, numpyy (add to artifact proxy deny-list)
- REPORT: Submit malware reports to [email protected] with package names and evidence
- MONITOR: Continue weekly scans for the full dependency watchlist

评论

支持 Markdown