Ir al contenido

Seguridad y operaciones del compilador de backport

Herramienta de compilación: NO es una dependencia en tiempo de ejecución. Esta página explica cómo operar el flujo de compilación y cómo confiar en él. La postura de seguridad del motor PDF se documenta junto con el propio motor, no aquí.

El compilador transforma código fuente que no es de su autoría y emite una distribución que no mantiene. Su modelo de seguridad se deriva de ese hecho. El límite de confianza está formado por el checkout del código fuente y la cadena de herramientas. El artefacto emitido es de solo lectura y se produce de forma automatizada. La separación de licencias entre los paquetes público y Pro está fijada en el código.

Las entradas del compilador son los repositorios de código fuente y la cadena de herramientas fijada. Su salida es un artefacto derivado. Se sostienen tres propiedades:

  • La distribución generada es de solo lectura y se produce de forma automatizada. Se publica en forma de etiquetas de versión, no como ramas de este repositorio. El desarrollo, los reportes de errores y las solicitudes de funcionalidades se dirigen a los repositorios de código fuente originales nextpdf/*, nunca al árbol generado. Verificado en el bloque de advertencia del README.md del proyecto y en .github/workflows/build.yml (la publicación confirma y etiqueta el árbol generado desde cero).
  • El alcance del token de publicación es reducido. secrets.BACKPORT_TRIGGER_TOKEN autoriza la clonación de los repositorios de código fuente en la etiqueta de publicación. Únicamente se referencia en los pasos de checkout del código fuente. Verificado en build.yml (uso de GH_TOKEN).
  • La separación de runners de CI es deliberada. Los eventos considerados de confianza se ejecutan en runners de PHP autoalojados; las pull requests desde forks y las ejecuciones de Dependabot se fuerzan a runners alojados en GitHub. El código no confiable nunca se ejecuta en el grupo de runners de confianza. Verificado en .github/workflows/0-ci.yml (la condición runs-on).
  • La cadena de herramientas está restringida en composer.json. Rector ^2.0, PHPStan ^2.1, PHPUnit ^13.0 y el conjunto symfony/polyfill-*. El compilador no tiene ninguna dependencia en tiempo de ejecución de NextPDF, por lo que el compromiso de un paquete en tiempo de ejecución de NextPDF no puede propagarse al compilador. Verificado en composer.json.
  • Las actualizaciones de dependencias están impulsadas por bots y controladas por puertas. Existe una configuración de Dependabot y un flujo de auto-merge; las ejecuciones de Dependabot se fijan a runners alojados en GitHub y, aun así, pasan por la puerta completa de CI (PHPStan, pruebas, dry-run) antes de fusionarse. Verificado en .github/dependabot.yml y .github/workflows/0-ci.yml, 9-dependabot-auto-merge.yml.
  • La salida excluye el estado de compilación. El archivo de publicación se comprime con vendor/ y .git/ excluidos, de modo que el artefacto publicado contiene el código fuente y el manifiesto generado, no el árbol de dependencias del propio compilador. Verificado en build.yml (zip ... -x '*/vendor/*' '*/.git/*').
  • El análisis estático controla el código de compilación. composer analyse ejecuta PHPStan en el nivel 10 sobre rector/rules y scripts en cada push y pull request a cualquiera de las dos ramas permanentes. Se ejecuta antes de cualquier dry-run. Verificado en composer.json y 0-ci.yml.

El script de compilación no valida localmente la sintaxis de la salida. La razón es que el host de compilación ejecuta una versión de PHP más reciente que la de destino. La puerta con autoridad está en el flujo de publicación. Tras la compilación, el runner cambia al PHP de destino y ejecuta php -l sobre output/src, lo que hace fallar la publicación ante cualquier error de análisis o fatal. A continuación, el artefacto se instala y se somete a toda la matriz de validación: desde PHP 8.1 hasta 8.4 para la línea de PHP 8.1, y PHP 7.4 y 8.0 para la línea de PHP 7.4. Una distribución que un entorno de ejecución de destino rechazaría no llega a publicarse. Verificado en scripts/build.php (validateOutput()) y .github/workflows/build.yml (la verificación de sintaxis y los trabajos validate-*).

Esta es una garantía basada en comportamiento observado, acotada a los entornos de ejecución que el flujo ejercita. No es una certificación de conformidad. No afirma la corrección del programa transformado más allá de la aceptación de la sintaxis y del propio conjunto de pruebas del proyecto.

Los dos paquetes producidos llevan licencias distintas, fijadas en scripts/adjust-composer.php:

PaqueteCampo de licenciaEstablecido por
nextpdf/backportApache-2.0generatePublicComposer()
nextpdf/backport-proproprietarygenerateProComposer()

El propio repositorio del compilador es Apache-2.0 (composer.jsonlicense). Su CHANGELOG.md registra un cambio previo de licencia de LGPL-3.0-or-later a Apache-2.0. Las versiones publicadas antes de ese cambio permanecen bajo la licencia anterior y siguen pudiéndose recuperar, mientras que cada versión nueva es Apache-2.0. La distribución Pro es propietaria, se produce únicamente para el destino PHP 8.1 y requiere phpseclib/phpseclib ^3.0. Verificado en CHANGELOG.md, composer.json y scripts/adjust-composer.php.

Lo que garantiza el flujo, dentro de lo que impone el código:

  • Detención al primer fallo. La compilación se aborta en la primera etapa que falla, con un error identificado. Nunca se publica una distribución parcial, porque los trabajos de publicación dependen de una compilación y una validación correctas. Verificado en scripts/build.php (step()) y en el needs del trabajo de build.yml.
  • Compilaciones serializadas. El grupo de concurrencia backport-build con cancel-in-progress: false evita que dos publicaciones de origen compitan por la misma etiqueta de publicación. Verificado en build.yml.
  • Entradas reproducibles. El flujo clona cada repositorio de código fuente en la etiqueta de publicación exacta antes de compilar. Verificado en build.yml (--branch "${TAG}").

Lo que no afirma:

  • No certifica la conformidad con estándares, la compatibilidad completa con las versiones de PHP ni la corrección del programa transformado más allá de la aceptación de la sintaxis y del conjunto de pruebas.
  • El downgrade elimina la inmutabilidad impuesta en tiempo de ejecución (al eliminar readonly). El código que dependía del entorno de ejecución para rechazar una escritura en una propiedad readonly pierde esa defensa en la salida degradada. Se trata de una concesión documentada e intencionada a favor de la seguridad de clone-with — consulte /integrations/backport/troubleshooting/.

Los problemas de seguridad en el compilador siguen el SECURITY.md del repositorio: deben notificarse a través de un GitHub Security Advisory o del contacto de seguridad, no mediante una incidencia pública. Los problemas en el código generado se notifican contra los repositorios de código fuente originales, porque el árbol generado se produce de forma automatizada y no es objeto de desarrollo. Verificado en SECURITY.md y en el README.md del proyecto.

  • /integrations/backport/overview/ — qué es el compilador y qué produce.
  • /integrations/backport/production-usage/ — cómo operar el flujo de publicación.