自托管的 AI 工作空间,包含代理、技能和工具(Gmail、日历),完全基于你自己的提供商 API 密钥(BYOK)运行。自带密钥——Groq、OpenRouter、NVIDIA、Hugging Face、Google AI。
针对 org.asynchttpclient:async-http-client(AsyncHttpClient,简称 "AHC")的 26 条仓库级安全公告的离线检查工具。
它会告诉你你的 jar 实际暴露于哪些公告,标记出 Dependabot 和 OSV 无法看到的那些,并为每一行给出一个答案:
3.0.142.16.1
仍受 5 条不会修复的公告影响。唯一的修复方式是迁移到 3.0.14。单个 jar,零运行时依赖,完全离线,Java 17+。
更正(2026-10-12,v0.2.0)。 本工具及 README 的 v0.1.0 曾称:"全局数据库 仅列出 17 条中的 4 条"、"Dependabot 告诉你安装 3.0.12"、"真正的答案是
3.0.13/2.16.1"。这三条在 2026-09-19 均为真,而如今均已不再成立: 上游于 2026-09-24 又发布了 5 条公告(在3.0.14中修复,2.x 上未修复),并且 在 2026-10-08,GitHub 全局数据库又收录了 9 条条目。v0.1.0 将3.0.13和2.16.1报告为干净——它们并非如此。请使用 v0.2.0。
2026-09-24,维护者发布了五条公告。每一条的 Patches 部分都以 同一句话结尾:
2.x 系列已停止维护,将不会获得修复。请升级到 3.0.14。
这五条都列出了一个以 2.16.1 结尾的 2.x 范围——即 Maven Central 上最新的 2.x 版本——且
修复版本为空:
| 公告 | 严重性 | 2.x 范围 | 内容 | 需要 |
|---|---|---|---|---|
CVE-2026-107230 | 高 | >= 2.0.0, <= 2.16.1 | 池化连接在 NTLM / Negotiate / 代理登录之间仍被共享(GHSA-vvp4-63h8-v5pm 的不完整修复) | 对源站或代理使用 NTLM、Kerberos 或 SPNEGO,或在 SOCKS / CONNECT 代理上进行任何登录,并且通过一个客户端以不同身份发起请求。对源站使用 Basic 和 Digest 不受影响 |
CVE-2026-107227 | 高 | >= 2.2.0, <= 2.16.1 | WebSocket permessage-deflate 消息在解压时没有大小限制 | setEnablewebSocketCompression(true)——默认关闭——以及一个不受信任或明文的 WebSocket 服务器 |
CVE-2026-107228 | 中 | >= 2.1.0, <= 2.16.1 | 通过 setHeader / addHeader 设置的 Cookie 头会被 cookie 存储的 cookie 替换(绕过 CVE-2024-53990 修复) | cookie 存储,默认开启,持有该源站的任何 cookie |
CVE-2026-107226 | 中 | >= 2.1.0, <= 2.16.1 | 通过明文 HTTP 接收的 cookie 可以植入、覆盖或删除通过 HTTPS 设置的 Secure cookie | 同一站点的明文与 HTTPS 源站之间共享一个 cookie 存储 |
CVE-2026-107229 | 中 | >= 2.16.0, <= 2.16.1 | 默认 cookie 存储中的源站检查不完整(公共后缀私有段、IP 主机等) | 一个客户端访问多个源站,其中一个是受攻击者影响的 |
对两个高危漏洞要精确理解: 两者都不适用于使用默认设置执行普通请求的客户端。CVE-2026-107227 需要开启 WebSocket 压缩;CVE-2026-107230
需要 NTLM / Kerberos / SPNEGO 或一个需要认证的代理。三个中危漏洞才是
触及默认 cookie 存储的那些。本工具不知道你如何使用客户端;它报告版本范围所说明的内容,
把判断留给你。
它确实改变的是:"升级到 2.16.1" 不再是答案。 较旧的 2.x 版本(例如
2.12.3)可以升级到 2.16.1 以清除那些确实有 2.x 修复的公告——而在此之后
它仍处于上述五个范围之内(从低于 2.16.0 升级甚至会新增
CVE-2026-107229,其范围从 2.16.0 开始)。工具会准确打印这一点,并对 2.16.1
以退出码 1 退出。
Dependabot 和 OSV 不读取项目自己的 Security → Advisories 页面。它们读取的是
GitHub 全局公告数据库。截至 2026-10-12,对 26 条仓库公告中的 9 条,
GET /advisories/<GHSA> 返回 404:
CVE-2026-107281、CVE-2026-107279、CVE-2026-107232、
CVE-2026-107284、CVE-2026-102740、CVE-2026-102737、CVE-2026-85718、CVE-2026-85719)——
其中两个被维护者评为高危(CVE-2026-107232、CVE-2026-85719),均与
代理凭据有关;CVE-2026-107229)。数据库一直在追赶——8 月批次中有 4 个于 2026-09-17 到达,另有 5 个于
2026-10-08 到达——因此这个数字还会继续变化。每次命中都会打印
Dependabot/全局库:已收录 / 未收录(“已收录 / 未收录于全局数据库”),并且该工具会打印其表格
生成的日期。tools/recheck_before_publish.py 会告诉你该差距今天是否仍然存在。
对于 3.x,实际后果现在很小:仅根据全局数据库计算,
目标版本同样是 3.0.14。对于 <= 3.0.11 的版本,两个缺失的高危公告根本不会
展示给你。
还有一个值得了解的差异:CVE-2026-107282 被维护者评为 高危,而在全局数据库中
为 严重。规则表保留维护者的评级。
CVE-2026-85721(高危)是适用于 默认设置 的那一个:自动响应
解压缩默认开启,并且 HTTP/1.1 路径在解压响应体时对总大小没有任何限制。
恶意或被攻陷的服务器——或任何能够篡改传输中响应的人——可以发送一个
很小的 gzip/deflate 响应体,从而耗尽堆内存。受影响:<= 3.0.11 和 <= 2.16.0。
这一个 确实 在全局数据库中,因此 Dependabot 会对其发出告警。
这些范围混用了 >=、<=、<、显式的 = 3.0.12 以及裸写的 3.0.0。同一个 3.0.11 对于
CVE-2026-55688(< 3.0.11)是 安全 的,而对于 CVE-2026-107232
(<= 3.0.11)则是 受影响 的。规则表完全按照原文保留每个运算符;
tools/gen_rules.py 中的断言和一个单元测试会在边界不再如此表现时失败。解析器无法识别的任何范围
片段都会被视为错误——绝不会是“不受影响”。空的修复版本
仅在公告文本本身说明该版本线已终止支持时才被接受;它会被
存储为“该版本线无修复”,绝不会是“不受影响”。
当仓库和全局数据库都包含某条公告但在范围上不一致时,
规则表取 并集。目前有:CVE-2024-53990(仓库只列出 3.x 版本
3.0.0,全局数据库还列出 2.x >= 2.1.0, < 2.12.4)和 CVE-2026-107230(范围相同,
一侧写作 <= 3.0.13,另一侧写作 < 3.0.14)。
pom.xmlAHC 通常是 传递性 依赖,由 SDK 或客户端库引入。该 artifactId
可能永远不会出现在你的 pom.xml 中。此工具读取实际随包发布的 jar 中的
META-INF/maven/org.asynchttpclient/async-http-client/pom.properties——包括嵌套在
Spring Boot fat-jar(BOOT-INF/lib)或 WAR(WEB-INF/lib)中的 jar。
旧版 1.x 坐标 com.ning:async-http-client 具有相同的 artifactId;它会被列出,但不会
被判定。
java -jar async-http-client-check.jar target/ # scan build output
java -jar async-http-client-check.jar myapp.jar # fat-jar / war, nested jars included
java -jar async-http-client-check.jar --version-of 2.16.1 # judge a version directly
每条命中都会打印 ID、严重程度、标题、影响范围、修复版本(或 无(2.x 线已停止维护) —— 即“无,2.x 线已停止维护”),以及全局数据库是否收录该条目。输出为中文。
| 退出码 | 含义 |
|---|---|
0 | 不受这 26 条中任何一条影响,且每个文件都确实被读取 |
1 | 受影响 —— 包括 2.16.1,v0.1.0 曾将其报告为 0 |
2 | 无法判断 —— 参数错误、未找到 AHC jar、无法识别的版本,或超出已发布范围之外的预发布版本 |
4 | 某些文件无法读取 —— 不是 zip、被截断,或 I/O 失败 |
“我无法读取它”和“你是安全的”必须是两句不同的话。一个合法的空 jar(仅含 22 字节的 EOCD 记录)不算读取失败。如果某个文件受影响且另一个文件无法读取,退出码仍为 1。
async-http-client。 AHC 所依赖的 Netty jar 中的 Netty CVE 不在覆盖范围内。3.0.15,或全局数据库可能补充缺失的条目 —— 这种情况已经发生过一次(见顶部的更正)。src/main/java/dev/mikko/ahccheck/RuleTable.java 是生成的,从不手工编辑:
python tools/gen_rules.py --dry # run the assertions only
python tools/gen_rules.py # regenerate the table
它读取仓库级公告(vulnerable_version_range、patched_versions),在全局数据库中逐一查找,并将“对 Dependabot 可见:是/否”记录为每条规则的字段。必须通过七项断言,否则不会写入任何内容:公告数量以及全局数据库中缺失的 9 条公告的确切集合仍与基线一致;空修复版本仅出现在 2.x 系列上,且仅出现在公告文本包含生命周期终止语句的位置;3.x 的交集为 3.0.14,且五个未修复的 2.x 公告集合保持不变;这些版本从 Maven Central 返回 200,哨兵值返回 404,且 Maven Central 没有比 2.16.1 更新的 2.x 版本;2.16.1 恰好命中这五个,3.0.13 命中五个且均在 3.0.14 中修复,而 3.0.14 一个都不命中;所有运算符样式均存在,且边界情况仍然翻转;仓库与全局数据库之间的分歧仍然恰好是已知的那些。
真实 jar 的端到端检查位于 tools/e2e_real_jars.py(来自 Maven Central 的实际 jar,包括一个 fat-jar 和一个 WAR)。tools/recheck_before_publish.py 使用独立来源重新验证这些声明——OSV 表示 3.0.14 是干净的而 2.16.1 不是——再加上全局数据库和 Maven Central,每项都带有阳性对照和哨兵值,如果任何内容发生变化则以非零状态退出。
Apache License 2.0 — 参见 LICENSE。