Enterprise 版本
内容解除与重构(CDR)
NextPDF Enterprise 通过内容解除与重构(CDR)来中和一份不受信任的 PDF:它解析文件、对照接纳限制进行检查、检测危险特性、移除它们,并从剩余的对象重建一个新文件。这些危险特性是活动内容——内嵌脚本、启动动作、内嵌文件、富媒体等等——查看器可能会执行或据此采取动作。本页为行为层面:它说明引擎接纳什么、剥离什么、重建什么,以及为什么其输出不是一份证据性副本。
CDR 是一种破坏性、单向的变换。重建后的输出是输入的一份安全投影,而非一份被保存的或哈希等价的副本。该边界陈述于安全与合规。
前提条件已在前置数据中陈述,并在前提条件处重述。
版本与授权
标题为“版本与授权”的章节该能力随 NextPDF Enterprise(nextpdf/enterprise)发行,并以一份 Enterprise 层级的授权信封激活。没有该授权的部署不会加载该能力的类。NextPDF Core 与 NextPDF Pro 不提供 CDR。引擎在进程内运行;不受信任的文档在你的主机上被解析与重建。比较各版本并获取授权。
该能力做了什么
标题为“该能力做了什么”的章节PDF 支持查看器可以执行或据此采取动作的活动内容。依据 ISO 32000-2 §12.6.4,一个 ECMAScript 动作会使 PDF 处理器执行一段可以改变字段值与外观的脚本。依据 ISO 32000-2 §12.6.4,一个启动动作会启动一个应用程序,或打开或打印一份文档。依据 ISO 32000-2 §7.7.4,名称字典中的文档级脚本会在文档被打开时自动运行。CDR 移除这些面。
引擎运行一条有序的管线:
- 解析输入 PDF。
- 接纳控制 —— 验证文档处于接纳边界之内(对象数量、页数、解码后的流大小,以及一个用于防御解压炸弹输入的流膨胀比)。处于限制之外的文档会被拒绝,而非被清洗。该拒绝与清洗结果分别报告,以便你的错误处理能区分两者。
- 检测威胁 —— 扫描所配置的威胁类型。
- 过滤 —— 把对象划分为安全集与移除集。
- 引用清洗 —— 清理因移除而悬空的指针。
- 重建 —— 把安全对象序列化进一个新的 PDF。
可检测的威胁类型包括内嵌脚本(以及能够捕获畸形结构中脚本的激进脚本剥离)、附加动作与打开动作触发器、启动动作、远程跳转动作、表单提交与导入数据动作、内嵌文件、富媒体与三维内容、文档级脚本名称树、外部统一资源标识符(URI)动作、XML 表单架构数据、交互式表单字段、非默认的可选内容图层,以及数字签名对象(一次重建必然会使其失效,因为字节范围不再匹配)。无法被解析的对象本身被视为一种潜在绕过并被移除。
三种策略设定默认值:
- Standard —— 移除引擎可检测、已配置的活动内容威胁类型;增量更新始终被扁平化以防御签名遮蔽,且该扁平化在此模式下不可配置。
- Paranoid —— 相同的移除,但资源限制更严。
- Permissive —— 用于受信任的来源:移除脚本与启动动作,但保留 URI 动作,并使增量更新扁平化可配置。
为何这样设计
标题为“为何这样设计”的章节CDR 从它判定为安全的对象重建一个新文件,而不是原地删除危险的键。这种允许列表(allow-list)姿态是承重性的决策。检测器从未识别的对象——包括它无法解析的对象——不会存续进入输出,因此一个未知结构会失败关闭(fail closed),而不是从拒绝列表(deny-list)的缝隙中溜过去。接纳控制出于同样的原因先行运行:超限或无法解析的输入会被直接拒绝,绝不部分重建。这份安全的代价是保存性。重建会改变字节布局、使签名失效,并丢弃其威胁类型被剥离的载荷——这正是为什么其输出是一份安全投影,而绝非一份证据性副本。
设计背景:清洗不受信任的 PDF:内容解除与重构。
前提条件
标题为“前提条件”的章节- 安装 NextPDF Core 与 Enterprise 包,并持有一份有效的 Enterprise 授权。
- 为你的输入定义接纳边界——最大对象数量、页数、解码后的流大小,以及膨胀比——或者使用某个预设策略的限制。
- 决定策略:用于一般不受信任接收的 standard、用于最严格姿态的 paranoid,或仅用于受信任来源的 permissive。
策略是不可变的,并携带:
- 要移除的威胁类型 —— 检测器扫描、重建器剥离的那一组。
- URI 动作处理 —— 是否保留外部 URI 动作。
- 增量更新扁平化 —— 在 standard 与 paranoid 中始终开启;在 permissive 中可配置。
- 接纳限制 —— 最大对象数量、页数、解码后的流大小,以及膨胀比。这些是接纳边界,而非清洗行为;超过它们会拒绝该文档。
分步操作
标题为“分步操作”的章节- 读取不受信任的 PDF 字节。
- 选择一个策略(standard、paranoid 或 permissive),或用显式限制构建一个。
- 用这些字节与该策略运行引擎的清洗操作。
- 检视结果:如果它报告未被接纳,请呈现拒绝原因;否则使用重建后的字节与已移除威胁的列表。
- 把重建后的输出当作一份经清洗的投影,绝不要把它当作输入的证据性或归档性副本。
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Enterprise\Security\Cdr\CdrEngine;use NextPDF\Enterprise\Security\Cdr\CdrPolicy;use NextPDF\Enterprise\Security\Cdr\CdrResult;use Psr\Log\LoggerInterface;
final readonly class UntrustedPdfIntake{ public function __construct( private CdrEngine $engine, private LoggerInterface $logger, ) {}
/** * Sanitize an untrusted PDF and distinguish rejection from a clean rebuild. * * An over-limit document is rejected by admission control, not sanitized; * the caller surfaces the rejection reason instead of trusting an empty * output. The rebuilt bytes are a security projection, never an * evidentiary copy of the input. * * @param string $pdfBytes The untrusted PDF bytes. * * @return CdrResult The sanitization result, including admission status. */ public function sanitize(string $pdfBytes): CdrResult { $result = $this->engine->sanitize($pdfBytes, CdrPolicy::standard());
if (! $result->admitted) { $this->logger->warning('PDF rejected by CDR admission control', [ 'reason' => $result->rejectionReason, ]);
return $result; }
$this->logger->info('PDF sanitized', [ 'removedThreats' => \count($result->removedThreats), 'originalSize' => $result->originalSize, 'sanitizedSize' => $result->sanitizedSize, ]);
return $result; }}- 运行一个携带已知活动内容面的样本(例如一段文档级脚本),并确认它出现在已移除威胁的列表中,且在重建后的输出中缺失。
- 运行一个超限文档,并确认结果报告未被接纳并附带拒绝原因,且重建后的字节为空。
- 确认一份带数字签名的输入在重建中其签名对象被移除——一次重建会使原始签名失效,因为字节范围改变了,所以失效的签名对象按设计被剥离。
- 在查看器中打开重建后的输出,并确认打开时没有脚本执行。
安全与合规
标题为“安全与合规”的章节- 不用于证据。 重建后的输出是一份破坏性、不可逆的投影。请不要把它用于法律证据保全、用于与原文件做哈希比对,或用作归档副本。如果你需要一份证据性副本,请将原文件置于单独的保管之下。
- 接纳先于清洗。 资源限制是一个接纳边界;超限文档会被拒绝,而非被清洗。请分别报告拒绝,使一个超限输入绝不会被误认为一次干净的重建。
- 活动内容被移除。 脚本、启动动作、文档级脚本名称树、内嵌文件、富媒体等面均被剥离——也就是查看器原本会执行的那些动作(ISO 32000-2 §12.6.4 ECMAScript 动作;启动动作;文档级脚本 §7.7.4)。
- 签名因重建而失效。 因为重建改变了字节布局,原始签名将不再能通过验证;签名对象被移除,而非误导性地原地保留。
- 按设计有损。 当其威胁类型被剥离时,内嵌文件载荷——包括诸如 Factur-X 这样的发票附件——会被移除。CDR 是一份安全投影,而非一个保存层。
本页涉及文档安全。每一项规范性来源都以转述方式呈现;不复现任何规范性原文。
失败处理
标题为“失败处理”的章节- 解析失败。 无法被解析的文档会产生一个未被接纳的结果并附带解析错误原因,而不是一次部分重建。
- 超限输入。 结果报告未被接纳并附带一个针对具体限制的原因;重建后的字节为空。
- 无法解析的对象。 无法被解析的对象被视为一种潜在绕过并被移除,而非静默保留。
- 尽力而为的页数。 页数接纳检查是尽力而为;一个畸形的 catalog 不会使管线崩溃,但对象数量与流限制仍然适用。
发布边界
标题为“发布边界”的章节本页仅记录外部可观察的行为与受支持的公共 API 接口。内部命名空间路径、辅助类、机制表、运行手册文件名,以及工单前缀均不在范围之内。
另请参阅
标题为“另请参阅”的章节- Security — NextPDF Enterprise —— 组合后的 Enterprise 安全接口。
- Validation — NextPDF Enterprise —— 对已生成或已重建 PDF 的符合性检查。
- Forensics — NextPDF Enterprise —— 文档检视与溯源。
- Security — NextPDF Core —— 核心的加密与签名接口。
- CDR · active content · shadow attack —— 术语表条目。