Modelo de amenazas del motor
De un vistazo
Sección titulada «De un vistazo»Esta página presenta el modelo de amenazas del motor central de NextPDF. Enumera las clases de ataque que el motor considera dentro de su alcance cuando procesa entradas influidas por un atacante (HTML, CSS, SVG, fuentes, imágenes y PDF existentes). Define la postura predeterminada de cada capacidad de recurso externo. Identifica la protección en el código que mitiga cada clase.
Límite. Un modelo de amenazas documenta las amenazas que se consideraron y las mitigaciones que se les aplicaron. No afirma la ausencia de vulnerabilidades. Que una clase no figure aquí no prueba su ausencia: puede estar fuera del alcance actual del modelo. Las funcionalidades no implementadas quedan sujetas a una revisión formal de amenazas antes de publicarse. Debe tratarse esta página como un registro de diseño deliberado, no como una prueba de seguridad.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Las protecciones descritas aquí forman parte del paquete del núcleo; no hace falta ninguna dependencia adicional para habilitarlas. Están activadas de forma predeterminada.
Panorama conceptual
Sección titulada «Panorama conceptual»El modelo sigue la estructura recomendada por el proceso de modelado de amenazas de OWASP (owasp_threat_modeling#x1.x11.p6): descomponer el sistema en los puntos donde una entrada no confiable cruza un límite de confianza, enumerar las amenazas en cada límite y registrar su mitigación.
El límite de confianza principal del motor es la ingesta de documentos: cualquier punto donde contenido creado en otro lugar —una hoja de estilos remota, una fuente @font-face, un <image href>, una factura XML incrustada, un PDF por inspeccionar— podría hacer que el motor obtenga, analice o descomprima algo. El principio rector es denegar de forma predeterminada: toda capacidad de recurso externo está DESACTIVADA hasta que quien la invoca la habilita explícitamente mediante un objeto de política. Esta es la línea base de mínima funcionalidad de NIST SP 800-53 Rev. 5 CM-7 (nist_sp_800_53r5#x4.x182.p14) aplicada a un motor de renderizado: la posición más estricta es el valor predeterminado del constructor. Abrir una capacidad es una decisión explícita de quien invoca.
Superficie de la API
Sección titulada «Superficie de la API»El modelo de amenazas no es, por sí mismo, una API. Los objetos de política que lo expresan están documentados en las páginas de los módulos; los puntos de entrada relevantes para la confianza son el contrato de política de recursos externos (ExternalResourcePolicyInterface, con DefaultExternalResourcePolicy como valor predeterminado de denegación total) y las protecciones de URL y XML (UrlValidator, XmlGuard). Esta página hace referencia a su comportamiento; no vuelve a documentar sus firmas.
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»La postura segura viene de forma predeterminada. No se requiere código para obtenerla:
<?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();Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»Abrir una capacidad debe ser una decisión deliberada y acotada. En producción, si se necesita permitir una fuente web alojada en una CDN sobre HTTPS, se opta por ello explícitamente y se acota:
<?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']);Casos límite y trampas
Sección titulada «Casos límite y trampas»- No implementado no es lo mismo que seguro por accidente. Capacidades como
background-image url()en CSS no están implementadas. Por lo tanto, no presentan ninguna superficie de ataque actual. Sin embargo, están documentadas como susceptibles de requerir una compuerta formal de amenazas antes de cualquier implementación futura. La ausencia de código es la mitigación de hoy, no una garantía permanente. - La reasignación de DNS es un objetivo en movimiento.
UrlValidatorresuelve el nombre de host y devuelve la IP resuelta para que quien invoca pueda fijar la conexión (CURLOPT_RESOLVE), lo que cierra la ventana TOCTOU entre validar y obtener. Esta es una defensa de mejor esfuerzo, no una defensa absoluta. Un operador detrás de un proxy de salida permisivo aún puede alcanzar hosts internos que la biblioteca no puede ver. - Los bits de permiso no son un control de acceso. Un documento que «bloquea la copia» depende de la cooperación del lector, no de una imposición efectiva. Esto se aborda en el modelo de seguridad. Se menciona aquí porque es un error conceptual frecuente sobre el modelo de amenazas.
Rendimiento
Sección titulada «Rendimiento»Las protecciones están diseñadas para fallar rápido y acotar el trabajo: la protección XML rechaza DOCTYPE antes de analizar y limita el tamaño de la entrada; la ruta de imágenes impone un techo de megapíxeles y de bytes antes de descomprimir; la protección de URL rechaza por scheme/host antes de abrir cualquier socket. El costo del valor predeterminado seguro es una solicitud rechazada, no una solicitud lenta.
Notas de seguridad
Sección titulada «Notas de seguridad»Las clases de ataque consideradas y sus mitigaciones en el código:
| Clase de amenaza (CWE / OWASP) | Vector en un motor de PDF | Protección en el código |
|---|---|---|
SSRF (OWASP Top 10 2025; owasp_top10_2025#x3.x1.p26) | @font-face/@import/url() apuntando a 169.254.169.254 o a un host interno; obtenedores de TSA/OCSP/CRL | UrlValidator::validateExternalUrl() bloquea rangos private/reserved/loopback/enlace-local y puntos de conexión de metadatos de la nube, rechaza esquemas peligrosos, resuelve el DNS y devuelve la IP para fijar la conexión |
XXE (cwe_top25_2025#x28.x2.p42) | Entidades externas / DOCTYPE en una factura XML incrustada o un paquete XMP | XmlGuard::loadXml() impone LIBXML_NONET y rechaza de plano cualquier declaración DOCTYPE, además de los caracteres de control prohibidos de XML 1.0, e impone un límite de tamaño de entrada |
| Bomba de descompresión | Imagen de 1×1 que enmascara una carga útil de 100 MP; WOFF2 de tamaño excesivo | La ruta de imágenes impone un techo de megapíxeles y un límite de bytes antes de descomprimir; la ruta de fuentes limita el tamaño de archivo y la cantidad de glifos |
| Recorrido de rutas | file:///etc/passwd desde una fuente o un SVG vía src | Los recursos externos se deniegan por completo de forma predeterminada; las rutas de archivos locales se resuelven mediante realpath() contra una lista de directorios permitidos cuando se habilita explícitamente |
| Inyección de contenido | Cadena manipulada que se escapa de un operador de PDF; data:/javascript: en href | Escapado de cadenas de PDF en la emisión; lista de esquemas permitidos y saneamiento de href en las anotaciones |
Los valores predeterminados se resumen como una postura de denegación total de recursos externos: las referencias a fuentes, @import, background-image y referencias externas de SVG están desactivadas hasta que quien invoca opta por habilitarlas por esquema, según la matriz de cobertura de propiedades de seguridad que se mantiene junto con el código.
Esta página documenta las amenazas consideradas. No es un informe de prueba de penetración y no afirma que las mitigaciones listadas sean completas ni que quede descartada cualquier otra clase de debilidad.
Conformidad
Sección titulada «Conformidad»No es un perfil de conformidad. El modelo de amenazas se basa en el proceso de modelado de amenazas de OWASP y en la taxonomía de debilidades CWE Top 25 (cwe_top25_2025#x28.x2.p42); no declara conformidad con ningún esquema de certificación de seguridad. La evaluación independiente corresponde a una auditoría, no a este documento.