Ir al contenido
getnextpdf.com

Enterprise edición

Desarme y reconstrucción de contenido — Referencia detallada

Esta página es la referencia detallada del módulo NextPDF\Enterprise\Security\Cdr. El módulo desarma un PDF no confiable y reconstruye un archivo limpio a partir de sus objetos seguros. La canalización es: análisis, control de admisión, detección de amenazas, filtrado, depuración de referencias, reconstrucción. La salida es una proyección de seguridad de la entrada, nunca una copia probatoria. Para orientación sobre flujos de trabajo, lea primero la página de la capacidad CDR.

Esta capacidad se distribuye en NextPDF Enterprise (nextpdf/enterprise) y se activa con un sobre de licencia de nivel Enterprise. Una implementación sin ese derecho no carga las clases de la capacidad. Compare ediciones y obtenga una licencia.

SímboloParámetrosComportamiento predeterminadoDevuelveLanza o falla conNotas
CdrEngine::__constructningunoConstruye el detector y el reconstructor internosCdrEngineNada declaradoSin colaboradores inyectables
CdrEngine::sanitizestring $pdfData, ?CdrPolicy $policy = nullEjecuta la canalización completa bajo CdrPolicy::standard()CdrResultNo lanza ante entradas hostiles; los fallos de análisis y admisión devuelven un resultado rechazadoEl resultado informa el rechazo de forma distinta al saneamiento
CdrPolicy::__constructsiete parámetros con nombre opcionales, ver el bloqueConjunto de eliminación vacío; allowUriActions false; flattenIncrementalUpdates true; límites de 100000 objetos, 256 MiB decodificados, 10000 páginas, 1000.0 de inflaciónCdrPolicyNada declaradofinal readonly; una lista removeThreatTypes vacía no detecta nada
CdrPolicy::standardningunoConjunto de amenazas heredado; acciones URI eliminadas; límites predeterminadosselfNada declaradoExcluye los siete casos con pérdida Strip*
CdrPolicy::paranoidningunoConjunto de amenazas heredado con límites más estrictos: 50000 objetos, 128 MiB, 5000 páginas, 100.0 de inflaciónselfNada declaradoExcluye los siete casos con pérdida Strip*
CdrPolicy::permissiveningunoElimina únicamente JavaScript, LaunchAction, NamedJavaScript, SubmitForm, ImportData; conserva las acciones URIselfNada declaradoPensado para fuentes confiables
CdrPolicy::allThreatTypesningunoDevuelve todos los casos de ThreatType, incluidos los casos con pérdida Strip*list<ThreatType>Nada declaradoLa opción explícita de eliminación máxima
CdrPolicy::legacyThreatTypesningunoDevuelve todos los casos excepto los siete casos Strip*list<ThreatType>Nada declaradoConjunto de eliminación predeterminado para standard() y paranoid()
CdrPolicy::shouldRemoveThreatType $typePrueba de pertenencia frente a removeThreatTypesboolNada declaradoDevuelve false para UriAction cuando allowUriActions es true
ThreatDetector::detectPdfReader $reader, CdrPolicy $policyEscanea cada objeto y el catálogo del tráiler en busca de los tipos de amenaza de la políticalist<DetectedThreat>No lanza; un objeto no analizable se convierte en una amenaza UnparseableObjectEl escaneo del catálogo cubre el árbol /Names/JavaScript
CdrRebuilder::rebuildPdfReader $reader, list<int> $safeObjNums, list<int> $removedObjNums, CdrPolicy $policySerializa objetos seguros en un archivo %PDF-2.0 de una sola revisiónstringNada declarado; los objetos que fallan en la relectura o en la validación de /Length se omiten$policy se reserva para futuros ajustes de serialización
DetectedThreat::__constructThreatType $type, int $objectNumber, string $description, string $location = ''Objeto de valor inmutable de hallazgoDetectedThreatNada declaradoLas cuatro propiedades son public readonly
ThreatTypeenum respaldado por cadenasVeinte casos: trece heredados más siete casos opcionales Strip*n/dn/dVer el inventario de casos a continuación
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: string

Trece casos heredados forman el conjunto de eliminación predeterminado. Los casos Strip* son con pérdida por diseño y nunca entran en una política predeterminada.

CasoValor de respaldoSuperficie de detección
ThreatType::JavaScriptjavascriptClave /JS en cualquier objeto, o una acción /S /JavaScript
ThreatType::AdditionalActionsadditional-actionsDiccionario /AA en cualquier objeto
ThreatType::OpenActionopen-actionClave /OpenAction en cualquier objeto
ThreatType::LaunchActionlaunch-actionAcción /S /Launch
ThreatType::RemoteGoToremote-gotoAcción /S /GoToR o /S /GoToE
ThreatType::SubmitFormsubmit-formAcción /S /SubmitForm
ThreatType::ImportDataimport-dataAcción /S /ImportData
ThreatType::EmbeddedFilesembedded-filesÁrbol de nombres /EmbeddedFiles o diccionario /EF
ThreatType::RichMediarich-media/Subtype /RichMedia
ThreatType::NamedJavaScriptnamed-javascriptÁrbol de nombres /Names/JavaScript del catálogo
ThreatType::UriActionuri-actionAcción /S /URI; suprimida cuando allowUriActions es true
ThreatType::XfaxfaClave /XFA
ThreatType::UnparseableObjectunparseable-objectCualquier objeto o catálogo que falla en el análisis
ThreatType::StripJavaScriptstrip-javascriptSuperconjunto opcional: clave /JS, /S /JavaScript o /Subtype /JavaScript
ThreatType::StripEmbeddedFilesstrip-embedded-filesOpcional: /Type /EmbeddedFile, /Type /Filespec, /EmbeddedFiles o /EF
ThreatType::StripFormFieldsstrip-form-fieldsOpcional: /Subtype /Widget, clave /FT o clave /AcroForm
ThreatType::StripAnnotationsRichstrip-annotations-richSubtipos opcionales: Movie, Sound, FileAttachment, 3D, RichMedia, Screen
ThreatType::StripOcgNonDefaultstrip-ocg-non-defaultOpcional: /Type /OCG con una clave /Usage o /Visibility
ThreatType::StripDigitalSignaturesAtRebuildstrip-digital-signatures-at-rebuildOpcional: /Type /Sig, /FT /Sig, /DSS, /VRI o /ByteRange
ThreatType::Strip3dAndRichMediastrip-3d-and-rich-mediaSubtipos opcionales: 3D, U3D, PRC, RMF, RichMedia, Sound, Movie

CdrEngine::sanitize ejecuta seis fases ordenadas y nunca lanza ante una entrada hostil.

  1. Análisis. Un fallo de análisis devuelve un resultado con admitted false y una razón de rechazo por error de análisis. La salida saneada está vacía en ese caso.
  2. Control de admisión. El recuento de objetos, los bytes agregados de flujos decodificados, la relación de inflación por flujo y el recuento de páginas se comprueban frente a los límites de la política. Un documento que excede los límites se rechaza, no se sanea. El rechazo y el saneamiento se informan de forma distinta.
  3. Detección. ThreatDetector::detect escanea cada objeto y el catálogo del tráiler en busca de los tipos de amenaza de la política. Los objetos no analizables se registran como hallazgos ThreatType::UnparseableObject en lugar de omitirse.
  4. Filtrado. Los objetos que portan hallazgos se ponen en cola para su eliminación. El catálogo del documento nunca se elimina como objeto completo. Los hallazgos a nivel de catálogo (OpenAction, AdditionalActions, NamedJavaScript) se remedian mediante la eliminación de claves.
  5. Depuración de referencias. Cada referencia indirecta a un objeto eliminado se reemplaza por null durante la serialización.
  6. Reconstrucción. CdrRebuilder::rebuild emite un archivo %PDF-2.0 de una sola revisión con objetos renumerados, una tabla de referencias cruzadas clásica y un tráiler nuevo. Los bytes de flujos seguros se copian de forma idéntica byte a byte. El catálogo reconstruido descarta /OpenAction, /AA y /Names; /AA se descarta de cada objeto.

El CdrResult devuelto expone los bytes reconstruidos, la lista de amenazas eliminadas, ambos tamaños en bytes, el indicador de admisión y la razón de rechazo. Si la fuente tenía un /Root resoluble y la salida reconstruida lo perdió, el motor rechaza la salida en lugar de devolver un archivo estructuralmente roto. Esta es una garantía a prueba de fallos: admitted true implica que la salida todavía porta una referencia al catálogo del documento.

Las actualizaciones incrementales nunca sobreviven: la reconstrucción serializa exactamente una revisión bajo cada política, de modo que las revisiones tardías de tipo sombra se aplanan por construcción. Las firmas digitales originales no pueden seguir siendo válidas tras una reconstrucción, porque los rangos de bytes ya no coinciden con la salida.

Línea roja de arquitectura. El CDR es una capa de proyección de seguridad, no una capa de preservación. La salida no debe usarse para la preservación de evidencia legal, la comparación de hash con el original ni las copias de archivo.

  • Una política null se resuelve a CdrPolicy::standard(). Una política construida con el removeThreatTypes vacío predeterminado no detecta ni elimina nada.
  • allowUriActions establecido en true suprime la eliminación de UriAction incluso cuando el caso está presente en removeThreatTypes.
  • flattenIncrementalUpdates es declarativo en esta versión: la reconstrucción emite una sola revisión bajo cada política, incluida permissive(), que establece el indicador en false.
  • La comprobación de la relación de inflación trata una longitud bruta de flujo de cero como uno, de modo que un flujo que se infla desde la nada sigue estando acotado. Cuando no se retiene ninguna forma decodificada, la longitud bruta del flujo cuenta para el presupuesto agregado.
  • La comprobación de admisión del recuento de páginas es de mejor esfuerzo: un fallo de lectura del catálogo o del árbol de páginas no rechaza por sí solo el documento. Los presupuestos de recuento de objetos y de descompresión siempre se aplican.
  • Un objeto cuya longitud bruta de flujo no concuerda con su entrada entera /Length se omite en el momento de la reconstrucción (defensa contra polyglot). Una referencia a un objeto así omitido conserva su número de objeto de origen y puede no resolverse en la salida. sanitize() rechaza los resultados detectablemente rotos (un /Root ausente), pero quien controla directamente el CdrRebuilder::rebuild() de bajo nivel debe revalidar por sí mismo la estructura de la salida y la integridad de las referencias.
  • Cuando el tráiler de origen porta /ID, el tráiler reconstruido porta un /ID aleatorio recién generado, no el original. Las demás entradas del tráiler, incluida /Info, no se transfieren; el tráiler reconstruido contiene /Size, /Root cuando es resoluble, y el /ID regenerado.
  • Los bytes de nombres y claves decodificados se reemiten con escapes hexadecimales para delimitadores, espacios en blanco y bytes no imprimibles, de modo que los nombres hostiles no puedan inyectar sintaxis de diccionario en la salida.
  • Los valores de cadena bajo claves de diccionario fuera del conjunto conocido con valor de nombre se emiten de forma conservadora como cadenas literales.
  • CdrPolicy::legacyThreatTypes() trata cualquier caso futuro del enum como eliminado por defecto a menos que esté registrado como un caso Strip*, de modo que los nuevos casos con pérdida no puedan entrar silenciosamente en las políticas predeterminadas.
  • El CDR no es un módulo criptográfico. Su único uso de aleatoriedad es el /ID del tráiler regenerado. La validación de firmas está fuera de alcance aquí; consulte la referencia detallada de firmas.
AfirmaciónEstándarCláusula
Invocar una acción ECMAScript hace que un procesador de PDF ejecute el script incrustado.ISO 32000-2§12.6.4.17
Los scripts a nivel de documento del árbol de nombres JavaScript se ejecutan todos al abrirse el documento.ISO 32000-2§12.6.4.17
El diccionario de nombres del catálogo puede contener un árbol de nombres JavaScript de acciones de script a nivel de documento.ISO 32000-2§7.7.4 (Table 32)
Una acción de lanzamiento inicia una aplicación, o abre o imprime un documento.ISO 32000-2§12.6.4.6
Los diccionarios de acciones adicionales /AA extienden los eventos desencadenantes en anotaciones, páginas, campos y el catálogo.ISO 32000-2§12.6.3
La admisión de archivos no confiables debe acotar la presencia, el volumen y el contenido de los archivos entrantes.OWASP ASVS 5.0§5.2
Los sistemas deben impedir la ejecución inapropiada de archivos subidos y detectar contenido peligroso.OWASP ASVS 5.0§5.3

Todas las cláusulas están parafraseadas; NextPDF no reproduce texto normativo. NextPDF no formula ninguna afirmación de certificación. El CDR elimina las superficies de contenido activo enumeradas por ThreatType bajo la política configurada; es una capacidad, no un saneador certificado. El CDR no es un escáner antivirus y no detecta firmas de malware; complementa, y no satisface, controles como el escaneo antivirus de OWASP ASVS 5.4.3. Si un archivo desarmado es aceptable para una canalización de admisión determinada sigue siendo la decisión de riesgo del operador.

  • La fuente del módulo lleva @since 1.9.0; esta referencia documenta la superficie tal como se distribuye en nextpdf/enterprise 3.1.0.
  • Todo se ejecuta en proceso en su host. No se produce ningún acceso a la red durante el saneamiento.
  • CdrPolicy y DetectedThreat son final readonly; construya una nueva instancia de política para cambiar los límites.
  • CdrEngine construye su detector y su reconstructor internamente. ThreatDetector y CdrRebuilder siguen siendo directamente utilizables para canalizaciones por etapas que aporten su propio PdfReader.
  • El parámetro $policy de CdrRebuilder::rebuild está actualmente reservado; la fuente lo documenta como conservado por compatibilidad con el sitio de llamada y para futuros ajustes de serialización por política.
  • La salida es estructuralmente reproducible, no reproducible bit a bit: el /ID regenerado difiere en cada ejecución cuando la fuente portaba uno.
  • El tipo de resultado CdrResult (valor de retorno de sanitize()) se cubre de forma conductual más arriba; sus campos son public readonly, con hadThreats() y threatCount() como conveniencias.

Esta página documenta únicamente el comportamiento observable externamente y la superficie de la API pública admitida. Las rutas de espacio de nombres internas, las clases auxiliares, las tablas de mecanismos, los nombres de archivo de runbooks y los prefijos de tickets están fuera de alcance.