针对
org.springframework.ai:spring-ai-pdf-document-reader中org.springframework.ai.reader.pdf.config.ParagraphManager的无限循环 / OOM 最小复现。已作为私有 GitHub 安全公告提交至
spring-projects/security-advisories。非公开披露。 本仓库仅用于负责任披露与验证。
ParagraphManager.generateParagraphs 通过 getNextSibling() 遍历大纲同级节点,但既无循环检测也无迭代上限。若 PDF 的大纲项将自身的 /Next 指针指向自己(即同级自环),则循环永不终止;每次迭代都会向父节点的 children 列表追加一个新的 Paragraph,最终以 耗尽 JVM 堆内存。
OutOfMemoryErrorCVE-2026-47851 修复中新增的检查(深度限制 + 已访问集合)仅覆盖 firstChild 循环,并未覆盖同级自环:深度永远不会超过第 1 层,且已访问集合仅记录 firstChild,因此同级节点永远不会进入该集合。因此,该变体在最新版本(2.0.1)上同样可以复现。
| 项目 | 值 |
|---|---|
| 受影响组件 | org.springframework.ai:spring-ai-pdf-document-reader |
| 受影响版本 | < 2.0.2(所有已知版本;1.x 和 2.0.0 甚至不包含 CVE-2026-47851 修复) |
| 漏洞类 | org.springframework.ai.reader.pdf.config.ParagraphManager |
| 触发方式 | 使用恶意 PDF 调用 new ParagraphPdfDocumentReader(resource) |
| 影响 | OutOfMemoryError,进程终止 — DoS |
| 严重性 | 7.5 高危 — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| 关联 | CVE-2026-47851(不完整修复) |
pom.xml — Maven 构建,依赖 spring-ai-pdf-document-reader:2.0.1
src/main/java/ReleaseVerify.java — 真实用户代码(官方 API 调用)
poc/selfloop.pdf — 396 字节恶意 PDF(同级自环)
poc/normal.pdf — 384 字节对照 PDF(除无 /Next 自引用外完全相同)
两个 PDF 仅相差12 字节 — selfloop.pdf 在大纲项中多了一个 /Next 5 0 R,将该条目指向自身作为其下一个同级节点。
mvn -q package
生成 target/springai-release-verify-1.0.0.jar(fat jar,包含 PDFBox 3.0.7)。
# 恶意 PDF — 数秒内 OOM
java -Xmx96m -cp target/springai-release-verify-1.0.0.jar ReleaseVerify para poc/selfloop.pdf
# 对照 PDF — 在 <100ms 内正常完成
java -Xmx96m -cp target/springai-release-verify-1.0.0.jar ReleaseVerify para poc/normal.pdf
OOM 发生在 ParagraphPdfDocumentReader 构造函数内部(该构造函数调用 new ParagraphManager(document));get() 永远不会被调用。
本仓库仅用于支持对私有报告公告的验证。这些 PDF 文件对 PDFBox 及任何其他合规的 PDF 解析器均无害;它们只会触发 Spring AI 的 ParagraphManager 遍历中的逻辑错误。请勿将其用于不属于您自己的系统。