Enterprise 版本
內容解除與重建(CDR)
NextPDF Enterprise 透過內容解除與重建(CDR)中和一份不可信的 PDF:它剖析檔案、對照接納限制檢查、偵測危險功能、移除它們,再從留下的物件重建一份新檔案。這些危險功能是主動內容——嵌入指令稿、launch action、嵌入檔案、rich media 等——檢視器可能會執行或據以行動。本頁屬於行為層級:它說明引擎接納什麼、剝除什麼、重建什麼,以及為何輸出不是一份具證據效力的副本。
CDR 是一種破壞性、單向的轉換。重建後的輸出是輸入的一份安全投影,而非一份被保存或雜湊等價的副本。該邊界陳述於 安全與合規。
先決條件陳述於前置資料中,並在 先決條件 處重申。
版本與授權
標題為「版本與授權」的區段此能力隨附於 NextPDF Enterprise(nextpdf/enterprise),並以一份 Enterprise 層級的授權封套啟用。不具該權利的部署不會載入此能力的類別。NextPDF Core 與 NextPDF Pro 不提供 CDR。引擎在行程內執行;不可信文件會在你的主機上被剖析與重建。比較各版本並取得授權。
此能力做了什麼
標題為「此能力做了什麼」的區段PDF 支援檢視器可以執行或據以行動的主動內容。一個 ECMAScript action 會使 PDF 處理器執行一段可變更欄位值與外觀的指令稿,依 ISO 32000-2 §12.6.4。一個 launch action 會啟動一個應用程式,或開啟或列印一份文件,依 ISO 32000-2 §12.6.4。name dictionary 中的文件層級指令稿會在文件開啟時自動執行,依 ISO 32000-2 §7.7.4。CDR 會移除這些介面。
引擎執行一條有序的管線:
- 剖析(Parse) 輸入的 PDF。
- 接納控制(Admission control) — 驗證文件在接納邊界之內(物件數量、頁面數量、解碼後串流大小,以及一個用來防禦解壓縮炸彈輸入的串流膨脹比)。超出限制的文件會被拒絕,而非清洗。拒絕會與清洗結果分開回報,因此你的錯誤處理能區分兩者。
- 偵測威脅(Detect threats) — 掃描所設定的威脅類型。
- 過濾(Filter) — 將物件分割為安全集合與被移除集合。
- 參照清洗(Reference scrub) — 清理因移除而懸空的指標。
- 重建(Rebuild) — 將安全物件序列化為一份新的 PDF。
可偵測的威脅類型包括嵌入指令稿(以及能在畸形結構中抓到指令稿的積極式指令稿剝除)、additional-actions 與 open-action 觸發器、launch action、remote go-to action、表單 submit 與 import-data action、嵌入檔案、rich media 與三維內容、文件層級指令稿名稱樹、外部統一資源識別碼(URI)action、XML Forms Architecture 資料、互動式表單欄位、非預設的選用內容圖層,以及數位簽章物件(重建必然會使其失效,因為位元組範圍不再相符)。一個無法被剖析的物件本身會被視為潛在的繞過手段並予以移除。
三種原則設定預設值:
- Standard — 移除引擎可偵測、所設定的主動內容威脅類型;增量更新一律被攤平以防禦簽章遮蔽(signature-shadowing),且在此模式下該攤平不可設定。
- Paranoid — 相同的移除,搭配更緊的資源限制。
- Permissive — 供受信任來源使用:移除指令稿與 launch action,但保留 URI action,並讓增量更新攤平可設定。
為何如此運作
標題為「為何如此運作」的區段CDR 從它判定為安全的物件重建一份新檔案,而非就地刪除危險的鍵。那個允許清單(allow-list)態勢是承重的決定。一個偵測器從未辨識的物件——包括它無法剖析的物件——不會存續到輸出中,因此一個未知結構會失敗關閉(fail closed),而非從拒絕清單(deny-list)的缺口溜過。接納控制基於同樣的理由率先執行:一份超出限制或無法剖析的輸入會被直接拒絕,絕不會被部分重建。那份安全的代價是保存性。重建改變了位元組配置、使簽章失效,並丟棄其威脅類型被剝除的酬載——這正是為何輸出是一份安全投影,而絕非一份具證據效力的副本。
設計背景:清洗不可信的 PDF:內容解除與重建。
先決條件
標題為「先決條件」的區段- 安裝 NextPDF Core 與 Enterprise 套件,並持有一份有效的 Enterprise 授權。
- 為你的輸入定義接納邊界——最大物件數量、頁面數量、解碼後串流大小與膨脹比——或使用某個預設原則的限制。
- 決定原則:standard 供一般的不可信收件、paranoid 供最嚴格的態勢,而 permissive 僅供受信任來源。
原則是不可變的,並承載:
- 要移除的威脅類型 — 偵測器掃描、重建器剝除的那組類型。
- URI action 處理 — 是否保留外部 URI action。
- 增量更新攤平 — 在 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; }}- 執行一個帶有已知主動內容介面的樣本(例如一段文件層級指令稿),並確認它出現在被移除威脅清單中,且不存在於重建後的輸出。
- 執行一份超出限制的文件,並確認結果回報未接納且附帶拒絕原因,而重建後的位元組為空。
- 確認一份數位簽署的輸入,其簽章物件在重建中被移除——重建會因位元組範圍改變而使原簽章失效,因此按設計會剝除過時的簽章物件。
- 在檢視器中開啟重建後的輸出,並確認開啟時沒有任何指令稿執行。
安全與合規
標題為「安全與合規」的區段- 不供作證據。 重建後的輸出是一份破壞性、不可逆的投影。請勿將它用於法律證據保存、與原件做雜湊比對,或作為封存副本。若你需要一份證據效力副本,請將原件置於另外的保管之下。
- 接納先於清洗。 資源限制是一道接納邊界;超出限制的文件會被拒絕,而非清洗。請將拒絕分開回報,使超出限制的輸入絕不會被誤認為一次乾淨的重建。
- 主動內容會被移除。 指令稿、launch action、文件層級指令稿名稱樹、嵌入檔案、rich media 等介面都會被剝除——正是檢視器原本會去執行的那些 action(ISO 32000-2 §12.6.4 ECMAScript action;launch action;文件層級指令稿 §7.7.4)。
- 簽章會因重建而失效。 因為重建改變了位元組配置,原簽章不再能驗證通過;簽章物件會被移除,而非誤導性地留在原處。
- 按設計有失真。 嵌入檔案的酬載——包括如 Factur-X 的發票附件——會在其威脅類型被剝除時一併移除。CDR 是一道安全投影,而非一個保存層。
本頁涉及文件安全。每一項規範性來源皆為改寫;不重製任何規範性文字。
失敗處理
標題為「失敗處理」的區段- 剖析失敗。 一份無法被剖析的文件會產出一個未接納結果並附帶剖析錯誤原因,而非一次部分重建。
- 超出限制的輸入。 結果會回報未接納並附帶特定限制的原因;重建後的位元組為空。
- 無法剖析的物件。 一個無法被剖析的物件會被視為潛在的繞過手段並予以移除,而非默默保留。
- 盡力而為的頁數計算。 頁數接納檢查屬於盡力而為;一個畸形的 catalog 不會使管線崩潰,但物件數量與串流限制仍然適用。
發佈邊界
標題為「發佈邊界」的區段本頁僅記錄外部可觀察的行為與受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表格、runbook 檔名與工單前綴皆不在範圍內。
另請參閱
標題為「另請參閱」的區段- Security — NextPDF Enterprise — 整合後的 Enterprise 安全介面。
- Validation — NextPDF Enterprise — 對已產生或已重建 PDF 的一致性檢查。
- Forensics — NextPDF Enterprise — 文件檢驗與追溯。
- Security — NextPDF Core — 核心加密與簽章介面。
- CDR · active content · shadow attack — 詞彙表條目。