Repository navigation
Releases: xiaoqiMikko/tomcat-check
Release list
v0.2.0
补进 Tomcat 官方 2026-08 与 2026-09 两批共 22 条 CVE(修复版 9.0.122 / 10.1.60 / 11.0.26),判定表现为 51 条。
- CVE-2026-86350(官方 Important)是修 CVE-2026-41293 时引入的回归,受影响区间 9.0.118–9.0.121、10.1.55–10.1.59、11.0.22–11.0.25,前提是启用 HTTP/2
- 新增 HTTP/2、WebSocket 两类触发条件;WebSocket 类条目只在扫到 tomcat-embed-websocket 时才算适用
- GitHub 尚未给出评级的条目显示「尚未评级」
用法:java -jar tomcat-check.jar <jar / war / 目录>(Java 17+)
v0.1.2
New exit code 4: some file could not be read.
Until now, an unreadable file (not a zip, truncated, or an I/O failure) only produced a line on
stdout while the exit code stayed 0. The printed warning is for humans; CI and scripts read
the exit code — so "I could not read it" silently meant "pass" in automation. A corrupt,
encrypted or partially downloaded jar quietly turned into "nothing found".
"I could not read it" and "you are safe" must be two different sentences.
0now means the scan finished and every file was actually read.4means at least one file could not be read.- A legitimately empty jar (a bare 22-byte EOCD record) is a real empty zip, not a broken file,
and does not trigger4— false alarms are what make real alarms get ignored. - Finding an actual affected version still wins: a real verdict is never downgraded to
4.
No existing exit code changed its meaning, and no CVE judgement changed.
Verified end-to-end across all three cases (non-zip / truncated / legitimately empty jar).
v0.1.1
Fix: an unreadable archive was silently reported as "nothing found".
ZipInputStream does not throw on non-zip content - it simply yields zero entries. A corrupt,
encrypted or truncated .jar used to walk through the whole scan and come out as "nothing found",
which reads as "you are not affected". "I could not read it" and "you are safe" must be two
different sentences.
Two layers, both needed:
- zip magic check - catches "not a zip at all";
- entry count after the walk - catches "magic is right but the content is truncated", which
the first layer lets through.
A legitimately empty zip (a bare 22-byte EOCD record) is flagged by neither - otherwise every empty
jar would become a false alarm.
Verified end-to-end against all three cases (non-zip / truncated / legitimately empty jar).
Also in this release: the version this tool prints is now checked against the POM version by a test,
so a release can no longer ship a jar that reports the wrong version number.
No change to any CVE judgement - the version numbers this tool reports are unchanged.
tomcat-check v0.1.0
零依赖单 jar,离线跑。需要 Java 17+。
它回答三个问题
1. 你的 Spring Boot 内嵌的是哪个版本的 Tomcat?
这个版本号由 spring-boot-starter-parent 的 tomcat.version 管着,你的 pom 里没有。
所以本工具扫构建产物(jar / fat jar / 安装目录),不读 pom。
2. 哪几条 CVE 不会出现在你的 Dependabot 告警里?
两种机制会让条目进不了告警:advisory 仍是 unreviewed(未标注受影响包,GitHub 只用 reviewed 的做告警),
或者 advisory 挂在 org.apache.tomcat:tomcat-coyote 这类坐标下 —— 而 Spring Boot 的依赖树里
只有 tomcat-embed-core / -el / -websocket。
实测:一个内嵌 Tomcat 9.0.118 的 Spring Boot 应用,Dependabot 面板全绿,本工具报出 4 条命中,
其中一条是默认配置即暴露。
3. 官方和扫描器给的评级差多少,以及触发条件是什么?
2026 年 27 条 CVE 里,17 条两套评级差 2 级以上。最极端的 CVE-2026-41293:
ASF 官方 Low,GitHub critical CVSS 9.8。
两套体系测量的是不同的东西 —— ASF 按默认配置下的实际可利用性,CVSS 按向量机械计算。
不是谁报错了,但要判断该不该现在升级,你需要同时看到它们,以及你有没有开那个功能。
用法
java -jar tomcat-check.jar target/my-app.jar # Spring Boot fat jar
java -jar tomcat-check.jar /opt/tomcat # 独立安装
java -jar tomcat-check.jar --all --utf8 target/lib请这样读它的输出
- 「命中」= 版本落在官方 Affects 区间内,不等于「已被利用」或「必然可利用」。
多数条目需要显式开启某个功能(RewriteValve、DIGEST 认证、AJP、WebDAV、集群通信)。 - 「Dependabot 不会告警」不是说 GitHub 失职 ——
unreviewed是正常流程状态。 - 判定表只覆盖 2026 年的 CVE,没有命中不等于没问题。
判定表
由 tools/gen_rules.py 从官方 security 页面 + GitHub Advisory API 两个一手源生成,
一行不手抄,带 6 条断言(含配对方向交叉校验、下真 jar 复验排除依据),任一不满足就中止。
32 个测试,运行时零依赖。