Enterprise エディション
Content Disarm and Reconstruction — 詳細リファレンス
本ページは NextPDF\Enterprise\Security\Cdr モジュールの詳細リファレンスです。本モジュールは信頼できない PDF を無害化し、その安全なオブジェクトからクリーンなファイルを再構築します。パイプラインは、解析、受け入れ制御、脅威検出、フィルタリング、参照スクラビング、再構築の順です。出力は入力のセキュリティ投影であり、証拠用のコピーでは決してありません。ワークフローのガイダンスについては、まず CDR 機能ページ をお読みください。
提供とライセンス
「提供とライセンス」という見出しのセクション本機能は NextPDF Enterprise(nextpdf/enterprise)で提供され、Enterprise ティアのライセンスエンベロープによって有効化されます。この権限を持たないデプロイでは、本機能のクラスは読み込まれません。エディションの比較とライセンスの取得。
公開 API サーフェス
「公開 API サーフェス」という見出しのセクション| シンボル | パラメーター | デフォルト動作 | 戻り値 | スロー/失敗条件 | 備考 |
|---|---|---|---|---|---|
CdrEngine::__construct | なし | 内部のディテクターとリビルダーを構築 | CdrEngine | 宣言なし | 注入可能なコラボレーターなし |
CdrEngine::sanitize | string $pdfData, ?CdrPolicy $policy = null | CdrPolicy::standard() の下で全パイプラインを実行 | CdrResult | 敵対的な入力でもスローしない。解析および受け入れの失敗は拒否結果を返す | 結果は拒否をサニタイズと区別して報告 |
CdrPolicy::__construct | 7 個のオプションの名前付きパラメーター、フェンス参照 | 除去セットは空。allowUriActions は false。flattenIncrementalUpdates は true。制限はオブジェクト 100000 個、デコード後 256 MiB、10000 ページ、膨張率 1000.0 | CdrPolicy | 宣言なし | final readonly。空の removeThreatTypes リストは何も検出しない |
CdrPolicy::standard | なし | レガシー脅威セット。URI アクションを除去。デフォルト制限 | self | 宣言なし | 損失を伴う 7 個の Strip* ケースを除外 |
CdrPolicy::paranoid | なし | より厳しい制限のレガシー脅威セット:オブジェクト 50000 個、128 MiB、5000 ページ、膨張率 100.0 | self | 宣言なし | 損失を伴う 7 個の Strip* ケースを除外 |
CdrPolicy::permissive | なし | JavaScript、LaunchAction、NamedJavaScript、SubmitForm、ImportData のみを除去。URI アクションは保持 | self | 宣言なし | 信頼できるソース向け |
CdrPolicy::allThreatTypes | なし | 損失を伴う Strip* ケースを含む、すべての ThreatType ケースを返す | list<ThreatType> | 宣言なし | 明示的な最大ストリップのオプトイン |
CdrPolicy::legacyThreatTypes | なし | 7 個の Strip* ケースを除くすべてのケースを返す | list<ThreatType> | 宣言なし | standard() と paranoid() のデフォルト除去セット |
CdrPolicy::shouldRemove | ThreatType $type | removeThreatTypes に対するメンバーシップ判定 | bool | 宣言なし | allowUriActions が true のとき UriAction に対して false を返す |
ThreatDetector::detect | PdfReader $reader, CdrPolicy $policy | ポリシーの脅威タイプについて、すべてのオブジェクトとトレーラーカタログをスキャン | list<DetectedThreat> | スローしない。解析不能なオブジェクトは UnparseableObject 脅威となる | カタログスキャンは /Names/JavaScript ツリーを対象とする |
CdrRebuilder::rebuild | PdfReader $reader, list<int> $safeObjNums, list<int> $removedObjNums, CdrPolicy $policy | 安全なオブジェクトを単一リビジョンの %PDF-2.0 ファイルにシリアライズ | string | 宣言なし。再読み込みまたは /Length 検証に失敗したオブジェクトはスキップされる | $policy は将来のシリアライズ調整のために予約 |
DetectedThreat::__construct | ThreatType $type, int $objectNumber, string $description, string $location = '' | 不変の検出結果値オブジェクト | DetectedThreat | 宣言なし | 4 個のプロパティはすべて public readonly |
ThreatType | 文字列バック列挙型 | 20 個のケース:13 個のレガシーに加え、7 個のオプトイン Strip* ケース | n/a | n/a | 以下のケース一覧を参照 |
エントリーポイントのシグネチャ
「エントリーポイントのシグネチャ」という見出しのセクションfinal class CdrEngine{ public function __construct()
public function sanitize(string $pdfData, ?CdrPolicy $policy = null): CdrResult}final readonly class CdrPolicy{ public function __construct( public array $removeThreatTypes = [], public bool $allowUriActions = false, public bool $flattenIncrementalUpdates = true, public int $maxObjects = 100_000, public int $maxDecodedStreamBytes = 268_435_456, public int $maxPageCount = 10_000, public float $maxInflationRatio = 1000.0, )
public static function standard(): self
public static function paranoid(): self
public static function permissive(): self
public static function allThreatTypes(): array
public static function legacyThreatTypes(): array
public function shouldRemove(ThreatType $type): bool}final class ThreatDetector{ public function detect(PdfReader $reader, CdrPolicy $policy): array}final class CdrRebuilder{ public function rebuild(PdfReader $reader, array $safeObjNums, array $removedObjNums, CdrPolicy $policy): string}final readonly class DetectedThreat{ public function __construct( public ThreatType $type, public int $objectNumber, public string $description, public string $location = '', )}enum ThreatType: stringThreatType ケース一覧
「ThreatType ケース一覧」という見出しのセクション13 個のレガシーケースがデフォルトの除去セットを構成します。Strip* ケースは設計上損失を伴い、デフォルトポリシーには決して含まれません。
| ケース | バッキング値 | 検出対象 |
|---|---|---|
ThreatType::JavaScript | javascript | 任意のオブジェクト上の /JS キー、または /S /JavaScript アクション |
ThreatType::AdditionalActions | additional-actions | 任意のオブジェクト上の /AA 辞書 |
ThreatType::OpenAction | open-action | 任意のオブジェクト上の /OpenAction キー |
ThreatType::LaunchAction | launch-action | /S /Launch アクション |
ThreatType::RemoteGoTo | remote-goto | /S /GoToR または /S /GoToE アクション |
ThreatType::SubmitForm | submit-form | /S /SubmitForm アクション |
ThreatType::ImportData | import-data | /S /ImportData アクション |
ThreatType::EmbeddedFiles | embedded-files | /EmbeddedFiles ネームツリー、または /EF 辞書 |
ThreatType::RichMedia | rich-media | /Subtype /RichMedia |
ThreatType::NamedJavaScript | named-javascript | カタログの /Names/JavaScript ネームツリー |
ThreatType::UriAction | uri-action | /S /URI アクション。allowUriActions が true のとき抑制 |
ThreatType::Xfa | xfa | /XFA キー |
ThreatType::UnparseableObject | unparseable-object | 解析に失敗する任意のオブジェクトまたはカタログ |
ThreatType::StripJavaScript | strip-javascript | オプトインのスーパーセット:/JS キー、/S /JavaScript、または /Subtype /JavaScript |
ThreatType::StripEmbeddedFiles | strip-embedded-files | オプトイン:/Type /EmbeddedFile、/Type /Filespec、/EmbeddedFiles、または /EF |
ThreatType::StripFormFields | strip-form-fields | オプトイン:/Subtype /Widget、/FT キー、または /AcroForm キー |
ThreatType::StripAnnotationsRich | strip-annotations-rich | オプトインのサブタイプ:Movie、Sound、FileAttachment、3D、RichMedia、Screen |
ThreatType::StripOcgNonDefault | strip-ocg-non-default | オプトイン:/Usage または /Visibility キーを持つ /Type /OCG |
ThreatType::StripDigitalSignaturesAtRebuild | strip-digital-signatures-at-rebuild | オプトイン:/Type /Sig、/FT /Sig、/DSS、/VRI、または /ByteRange |
ThreatType::Strip3dAndRichMedia | strip-3d-and-rich-media | オプトインのサブタイプ:3D、U3D、PRC、RMF、RichMedia、Sound、Movie |
動作コントラクト
「動作コントラクト」という見出しのセクションCdrEngine::sanitize は順序付けられた 6 つのフェーズを実行し、敵対的な入力に対して決してスローしません。
- 解析。 解析の失敗は、
admittedが false で解析エラーの拒否理由を持つ結果を返します。その場合、サニタイズ出力は空です。 - 受け入れ制御。 オブジェクト数、デコード後のストリームバイト合計、ストリームごとの膨張率、およびページ数がポリシー制限に照らして検査されます。制限を超えるドキュメントは、サニタイズされず拒否されます。拒否とサニタイズは区別して報告されます。
- 検出。
ThreatDetector::detectは、ポリシーの脅威タイプについてすべてのオブジェクトとトレーラーカタログをスキャンします。解析不能なオブジェクトはスキップされず、ThreatType::UnparseableObjectの検出結果として記録されます。 - フィルタリング。 検出結果を持つオブジェクトは、除去のためにキューへ入れられます。ドキュメントカタログがオブジェクト全体として除去されることはありません。カタログレベルの検出結果(
OpenAction、AdditionalActions、NamedJavaScript)は、代わりにキーのストリッピングによって修復されます。 - 参照スクラビング。 除去されたオブジェクトへのすべての間接参照は、シリアライズ中に
nullへ置き換えられます。 - 再構築。
CdrRebuilder::rebuildは、番号を振り直したオブジェクト、古典的なクロスリファレンステーブル、および新しいトレーラーを持つ単一リビジョンの%PDF-2.0ファイルを出力します。安全なストリームバイトはバイト単位で同一にコピーされます。再構築されたカタログは/OpenAction、/AA、/Namesを削除し、/AAはすべてのオブジェクトから削除されます。
返される CdrResult は、再構築後のバイト列、除去された脅威のリスト、両方のバイトサイズ、受け入れフラグ、および拒否理由を公開します。ソースに解決可能な /Root があり、再構築後の出力でそれが失われた場合、エンジンは構造的に壊れたファイルを返す代わりに出力を拒否します。これはフェイルクローズドの保証です。admitted が true であることは、出力が依然としてドキュメントカタログ参照を保持していることを意味します。
増分更新が残ることは決してありません。再構築はすべてのポリシーの下で正確に 1 つのリビジョンをシリアライズするため、シャドウ形式の後付けリビジョンは構造上フラット化されます。バイト範囲が出力と一致しなくなるため、元のデジタル署名は再構築をまたいで有効なまま保たれることはできません。
アーキテクチャのレッドライン。 CDR はセキュリティ投影レイヤーであり、保存レイヤーではありません。出力を、法的な証拠保全、オリジナルとのハッシュ比較、またはアーカイブコピーに使用してはなりません。
エッジケースと失敗モード
「エッジケースと失敗モード」という見出しのセクションnullポリシーはCdrPolicy::standard()に解決されます。デフォルトの空のremoveThreatTypesで構築されたポリシーは、何も検出せず何も除去しません。allowUriActionsをtrueに設定すると、そのケースがremoveThreatTypesに含まれている場合でもUriActionの除去が抑制されます。flattenIncrementalUpdatesは本リリースでは宣言的です。再構築は、フラグをfalseに設定するpermissive()を含むすべてのポリシーの下で、単一のリビジョンを出力します。- 膨張率のチェックは、生のストリーム長ゼロを 1 として扱うため、無からの膨張ストリームも依然として制限されます。デコード形式が保持されない場合、生のストリーム長が合計バジェットに算入されます。
- ページ数の受け入れチェックはベストエフォートです。カタログまたはページツリーの読み取り失敗だけでは、ドキュメントを拒否しません。オブジェクト数と解凍バジェットは常に強制されます。
- 生のストリーム長が整数の
/Lengthエントリと一致しないオブジェクトは、再構築時にスキップされます(ポリグロット防御)。そのようなスキップされたオブジェクトへの参照は、ソースのオブジェクト番号を保持し、出力内で解決されない場合があります。sanitize()は検出可能な壊れた結果(/Rootの欠落)を拒否しますが、低レベルのCdrRebuilder::rebuild()を直接駆動する呼び出し元は、出力構造と参照の整合性を自身で再検証する必要があります。 - ソースのトレーラーが
/IDを保持している場合、再構築されたトレーラーは元のものではなく、新たに生成されたランダムな/IDを保持します。/Infoを含むその他のトレーラーエントリは引き継がれません。再構築されたトレーラーは、/Size、解決可能な場合の/Root、および再生成された/IDを保持します。 - デコードされた名前とキーのバイトは、区切り文字、空白、および印字不能なバイトについて 16 進エスケープとともに再出力されるため、敵対的な名前が出力に辞書構文を注入することはできません。
- 既知の名前値セット外の辞書キーの下にある文字列値は、保守的にリテラル文字列として出力されます。
CdrPolicy::legacyThreatTypes()は、将来の列挙ケースがStrip*ケースとして登録されない限り、それをデフォルトで除去対象として扱うため、新しい損失を伴うケースが暗黙のうちにデフォルトポリシーへ入り込むことはありません。- CDR は暗号モジュールではありません。ランダム性を使用するのは、再生成されるトレーラーの
/IDのみです。署名検証はここでは対象外です。署名の詳細リファレンス を参照してください。
| 主張 | 標準 | 条項 |
|---|---|---|
| ECMAScript アクションの呼び出しにより、PDF プロセッサーは埋め込みスクリプトを実行する。 | ISO 32000-2 | §12.6.4.17 |
JavaScript ネームツリー内のドキュメントレベルスクリプトは、ドキュメントを開くときにすべて実行される。 | ISO 32000-2 | §12.6.4.17 |
カタログのネーム辞書は、ドキュメントレベルのスクリプトアクションの JavaScript ネームツリーを保持できる。 | ISO 32000-2 | §7.7.4 (Table 32) |
| ローンチアクションは、アプリケーションを起動するか、ドキュメントを開くか印刷する。 | ISO 32000-2 | §12.6.4.6 |
/AA 追加アクション辞書は、注釈、ページ、フィールド、およびカタログ上のトリガーイベントを拡張する。 | ISO 32000-2 | §12.6.3 |
| 信頼できないファイルの取り込みは、受信ファイルの存在、量、および内容を制限しなければならない。 | OWASP ASVS 5.0 | §5.2 |
| システムは、アップロードされたファイルの不適切な実行を防止し、危険な内容を検出すべきである。 | OWASP ASVS 5.0 | §5.3 |
すべての条項は言い換えられており、NextPDF は規範的なテキストを複製しません。NextPDF は認証の主張を一切行いません。 CDR は、設定されたポリシーの下で ThreatType によって列挙されるアクティブコンテンツのサーフェスを除去します。これは機能であり、認証されたサニタイザーではありません。CDR はアンチウイルススキャナーではなく、マルウェアのシグネチャを検出しません。OWASP ASVS 5.4.3 のアンチウイルススキャンなどのコントロールを補完するものであり、それらを満たすものではありません。無害化されたファイルが特定の取り込みパイプラインにとって受け入れ可能かどうかは、依然として運用者のリスク判断に委ねられます。
開発ノート
「開発ノート」という見出しのセクション- モジュールのソースには
@since 1.9.0が記載されています。本リファレンスは、nextpdf/enterprise3.1.0 で提供されるサーフェスを文書化しています。 - すべてがホスト上のプロセス内で実行されます。サニタイズ中にネットワークアクセスは発生しません。
CdrPolicyとDetectedThreatはfinal readonlyです。制限を変更するには、新しいポリシーインスタンスを構築します。CdrEngineは、そのディテクターとリビルダーを内部で構築します。ThreatDetectorとCdrRebuilderは、独自のPdfReaderを供給する段階的なパイプライン向けに、引き続き直接利用できます。CdrRebuilder::rebuildの$policyパラメーターは現在予約されています。ソースでは、呼び出し側の互換性と将来のポリシーごとのシリアライズ調整のために保持されていると文書化されています。- 出力は構造的に再現可能ですが、ビット単位で再現可能ではありません。再生成される
/IDは、ソースがそれを保持していた場合、実行ごとに異なります。 - 結果型
CdrResult(sanitize()の戻り値)は上記で動作面から扱われています。そのフィールドはpublic readonlyで、hadThreats()とthreatCount()を便宜的に備えています。
- Content Disarm and Reconstruction (CDR) — ワークフローとポリシーのガイダンスを含む機能ページ。
- セキュリティ — 詳細リファレンス
- 検証 — 詳細リファレンス
- フォレンジック — 詳細リファレンス
本ページは、外部から観測可能な動作とサポートされる公開 API サーフェスのみを文書化しています。内部の名前空間パス、ヘルパークラス、メカニズムテーブル、ランブックのファイル名、およびチケットのプレフィックスは対象外です。