引擎威胁模型
重点摘要
标题为“重点摘要”的章节本页是 NextPDF 核心引擎的威胁模型。它列举了引擎在处理受攻击者影响的输入(HTML、CSS、SVG、字体、图像,以及已有 PDF)时,视为范围内的攻击类别。本页说明每一种外部资源能力的默认姿态,并指出用于缓解各类别威胁的代码内防护。
边界。 威胁模型记录已考量的威胁,以及针对这些威胁所采取的缓解措施。它并不主张不存在漏洞。此处未列出的类别,并不因此就被证明不存在——它可能落在模型当前范围之外。尚未实现的功能在发布前必须通过正式的威胁审查把关。请把本页视为一份有意维护的设计记录,而非一份安全性证明。
composer require nextpdf/core:^3此处描述的防护属于核心包的一部分;无需额外依赖包即可启用。它们默认启用。
概念总览
标题为“概念总览”的章节本模型遵循 OWASP 威胁建模流程(owasp_threat_modeling#x1.x11.p6)建议的结构:将系统拆解为不受信任输入跨越信任边界的各个位置,列举每个边界上的威胁,并记录相应的缓解措施。
引擎的主要信任边界是 文档摄取(document ingestion):任何外部编写的内容进入引擎的位置——一份远程样式表、一个 @font-face 来源、一个 <image href>、一份内嵌的 XML 发票、一份待检查的 PDF——都可能指示引擎去抓取、解析或解压缩某个对象。其治理原则是 默认拒绝(deny-by-default):每一种外部资源能力在调用方通过策略对象明确启用之前,均处于关闭状态。这是将 NIST SP 800-53 Rev. 5 CM-7(nist_sp_800_53r5#x4.x182.p14)的最小功能性基准应用到渲染引擎上:最严格的立场就是构造函数的默认值。开启某项能力必须是调用方明确做出的决定。
API 接口
标题为“API 接口”的章节威胁模型本身并不是 API。表达该模型的策略对象记录在各模块页面中;与信任相关的入口点是外部资源策略契约(ExternalResourcePolicyInterface,以 DefaultExternalResourcePolicy 作为全部拒绝的默认值),以及 URL 与 XML 防护(UrlValidator、XmlGuard)。本页引用它们的行为,但不重新记录其签名。
代码示例——快速上手
标题为“代码示例——快速上手”的章节安全姿态就是默认值。无需编写任何代码即可获得它:
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Html\DefaultExternalResourcePolicy;
// Out of the box: @font-face blocked, @import blocked, background-image// blocked, SVG external refs blocked. A document that tries to fetch a// remote resource gets a system-font fallback or an ignored rule — not an// outbound request.$policy = new DefaultExternalResourcePolicy();代码示例——生产环境
标题为“代码示例——生产环境”的章节开启某项能力应当是有意且范围受限的。如果生产环境的调用方必须允许通过 HTTPS 加载 CDN 托管的 webfont,就需要明确选择启用并限定其范围:
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Html\DefaultExternalResourcePolicy;
// Explicit, scoped opt-in. The HTTPS scheme is required; size and glyph// caps still apply; the URL still passes the SSRF guard before any fetch.$policy = (new DefaultExternalResourcePolicy()) ->withFontFaceAllowed(['https']);边界情况与陷阱
标题为“边界情况与陷阱”的章节- 未实现不等于碰巧安全。 诸如 CSS
background-image url()这类能力尚未实现,因此它们当前的攻击面为零。但文档中已说明,它们在未来任何实现之前,都必须先通过正式的威胁 gate(把关)。代码的缺席是当前的缓解措施,而非永久保证。 - DNS 重新绑定是个不断变化的目标。
UrlValidator会 resolve(解析)主机名并返回解析后的 IP,让调用方可以固定该连接(CURLOPT_RESOLVE),借此关闭先验证后抓取之间的 TOCTOU 时间窗。这是尽力而为的防御,而非绝对防御。如果运维人员位于宽松的出口 proxy 之后,仍可能触及这套库看不见的内部主机。 - 权限位并不是访问控制。 一份「阻止复制」的文档依赖的是阅读器配合,而非强制执行。这一点已在安全模型一节中说明。这里特别指出,是因为它是常见的威胁模型误解。
这些防护的设计目标是快速失败并限制工作量:XML 防护在解析前拒绝 DOCTYPE 并限制输入大小;图像路径在解压缩前强制执行百万像素与字节上限;URL 防护在打开任何 socket 前按 scheme/host 拒绝请求。安全默认值的代价是一个被拒绝的请求,而不是一个缓慢的请求。
安全性注意事项
标题为“安全性注意事项”的章节所考量的攻击类别及其代码内缓解措施:
| 威胁类别(CWE / OWASP) | 在 PDF 引擎中的攻击向量 | 代码内防护 |
|---|---|---|
SSRF 服务器端请求伪造(OWASP Top 10 2025;owasp_top10_2025#x3.x1.p26) | @font-face/@import/url() 指向 169.254.169.254 或内部主机;TSA/OCSP/CRL 抓取器 | UrlValidator::validateExternalUrl() 封锁 private/reserved/loopback/link-local 范围与云端元数据端点、拒绝危险的 scheme,并解析 DNS 后返回 IP 以供连接固定 |
XXE(cwe_top25_2025#x28.x2.p42) | 内嵌 XML 发票或 XMP 数据包中的外部实体 / DOCTYPE | XmlGuard::loadXml() 强制执行 LIBXML_NONET 并直接拒绝任何 DOCTYPE 声明,另外也挡下 XML 1.0 禁用的控制字符,并设有输入大小上限 |
| 解压缩炸弹 | 用 1×1 图像掩饰一份 100 MP 的载荷;过大的 WOFF2 | 图像路径在解压缩前就强制执行百万像素上限与字节上限;字体路径则限制文件大小与字形数 |
| 路径穿越 | file:///etc/passwd,经由字体或 SVG 的 src | 外部资源默认全部拒绝;本地文件路径在明确启用时,会通过 realpath() 针对目录允许清单加以解析 |
| 内容注入 | 精心构造的字符串挣脱某个 PDF 运算符;data:/javascript: href | 输出时对 PDF 字符串进行转义;对注解采 scheme 允许清单加上 href 清理 |
这些默认值汇总为一个全部拒绝的外部资源姿态:字体、@import、background-image 与 SVG 外部引用在调用方逐一按 scheme 选择启用之前均保持关闭,这与随代码一同维护的安全性质覆盖矩阵一致。
本页记录的是 已考量 的威胁。它并不是一份渗透测试报告,也不主张所列缓解措施已经完整,或不存在其他类别的弱点。
符合性
标题为“符合性”的章节这并非一份符合性配置文件。本威胁模型参考 OWASP 威胁建模流程与 CWE Top 25 弱点分类法(cwe_top25_2025#x28.x2.p42);它并不主张符合任何安全认证方案。独立评估属于审计范畴,而非本文档范畴。