8 min de lectura

Compilaciones reproducibles para clientes de agentes locales

Las compilaciones reproducibles relacionan el binario de un cliente de agente local con el código fuente revisado, una receta de compilación documentada para macOS, etiquetas firmadas y artefactos verificables.

Compilaciones reproducibles para clientes de agentes locales

Un cliente de agente local está cerca de las credenciales y los permisos importantes. Si un desarrollador descarga uno y después le concede acceso a cuentas de API o destinos SSH, el binario del lanzamiento merece un análisis más riguroso que una captura de pantalla de una tarea de CI en verde. La pregunta útil es concreta: ¿puede alguien relacionar este ejecutable exacto con el código fuente que revisó y con un procedimiento de compilación que pueda volver a ejecutar?

Las compilaciones reproducibles responden a una parte de esa pregunta. No hacen inocuo un commit malicioso ni convierten una cuenta de desarrollador comprometida en una cuenta segura. Reducen una brecha distinta y frecuente entre el código revisado y el código distribuido. En esa brecha pueden esconderse un trabajador de compilación alterado, una dependencia sustituida o un cambio local accidental.

En un cliente de agente local como Sallyport, esto importa porque la aplicación realiza acciones mientras las credenciales permanecen fuera del proceso del agente. Los lectores deberían poder inspeccionar el código que gestiona ese límite y establecer qué binario de lanzamiento lo contiene, en lugar de aceptar sin más lo que dice una página de lanzamiento.

Una descarga firmada no demuestra que la haya producido el código fuente revisado

Una firma demuestra que quien posee una identidad de firma firmó los bytes entregados. No demuestra que esos bytes procedan del commit del repositorio que revisaste.

Los equipos suelen mezclar ambas afirmaciones porque las dos generan diálogos tranquilizadores en macOS. Gatekeeper y las comprobaciones de firma del sistema indican si el paquete tiene una cadena de firma válida y si alguien lo modificó después de firmarlo. No indican si el firmante compiló la etiqueta v1.2.3 sin parches locales, si CI usó una dependencia maliciosa o si quien publicó el lanzamiento sustituyó el archivo antes de ponerlo a disposición.

Esta diferencia cambia la forma de investigar un incidente. Si una aplicación tiene una firma válida pero se comporta de forma inesperada, la identidad de firma reduce el conjunto de personas y sistemas que podrían haberla producido. Una compilación reproducible puede reducir el conjunto de código fuente y recetas que produjeron el ejecutable. Necesitas ambas formas de evidencia porque cubren fallos diferentes.

La documentación de firma de código de Apple describe la firma como un sello sobre el paquete de código. Es una descripción precisa, pero un sello no dice nada de la cocina donde se montó el paquete. Trata la firma de código como integridad de distribución e identidad del editor. Trata la compilación independiente como verificación entre código fuente y binario.

Un lanzamiento también puede ser reproducible y seguir siendo peligroso. Si los revisores aceptaron un cambio defectuoso, una recompilación limpia producirá fielmente el programa defectuoso. No presentes la reproducibilidad como sustituto de la revisión, de los permisos de lanzamiento protegidos o de un diseño sensato de credenciales. Elimina la incertidumbre sobre la transformación del código fuente en artefacto.

Define la afirmación antes de comparar los bytes

El equipo debe indicar exactamente qué debe coincidir, porque el empaquetado de lanzamientos para macOS suele hacer imposible comparar un paquete completo después de firmarlo.

La afirmación más sólida es la reproducibilidad bit a bit: dos compilaciones independientes producen bytes idénticos. Es un buen objetivo para un ejecutable de línea de comandos sin firmar, un archivo de código fuente o un paquete determinista. Se complica cuando el proceso incorpora una marca de tiempo de firma, un perfil de aprovisionamiento, un ticket de notarización o una imagen de instalador generada.

No respondas abandonando la comparación. Divide el lanzamiento en fases y formula la afirmación con precisión. Un contrato práctico de lanzamiento podría decir:

  • La etiqueta Git firmada identifica el commit del código fuente.
  • El paquete de aplicación sin firmar que se compile desde ese commit debe coincidir byte por byte.
  • El firmante del lanzamiento añade después la identidad de firma y los permisos declarados.
  • El archivo publicado contiene el paquete firmado documentado, cuyo hash del ejecutable coincide con la salida comparable sin firmar.

Esto es más estricto que decir vagamente que CI compiló la aplicación, y más honesto que afirmar una identidad completa cuando la firma la hace inalcanzable. También dirige a los revisores hacia los archivos que se ejecutan. Una imagen de disco coincidente sirve de poco si su ejecutable de aplicación es distinto. Un ejecutable coincidente con permisos modificados merece atención inmediata, porque esos permisos pueden cambiar la autoridad disponible para un proceso.

Conviene mantener clara otra diferencia: compilaciones deterministas frente a lanzamientos verificables. Una compilación puede ser determinista en un equipo porque lee silenciosamente una caché local, la hora actual o una configuración del desarrollador. Un lanzamiento verificable ofrece pruebas suficientes para que otra persona obtenga las mismas entradas y compruebe la afirmación. Este segundo requisito obliga a los equipos a revelar supuestos que el primero puede ocultar.

Escribe la afirmación en el repositorio antes de la primera solicitud pública de verificación. Si los mantenedores no pueden decir si la comparación ocurre antes o después de firmar, los revisores externos no sabrán qué significa una diferencia.

El registro del lanzamiento debe vincular código fuente, receta y artefacto

Un registro de lanzamiento necesita una referencia firmada al código fuente, una receta inmutable y resúmenes criptográficos de los archivos que la gente descarga. Si falta cualquiera de estos elementos, se rompe la cadena de pruebas.

Empieza con una etiqueta Git anotada que nombre el lanzamiento. Un hash de commit por sí solo no es una declaración de lanzamiento: cualquiera puede dirigir una página web a un commit. La etiqueta debe llevar una firma de una identidad de mantenedor que los colaboradores sepan verificar. Después registra el objeto commit completo, no solo un identificador abreviado.

Un manifiesto mínimo puede seguir siendo texto plano y aportar pruebas útiles:

release: 1.2.3
source_tag: v1.2.3
source_commit: 4f3c1b6e8a0d2c7f9b5e1d4a6c8e0f2b3d7a9c1e
build_recipe: docs/release-build.md@4f3c1b6e8a0d2c7f9b5e1d4a6c8e0f2b3d7a9c1e
xcode: 16.2
macos: 15.2
architecture: arm64
unsigned_app_sha256: 9b74c9897bac770ffc029102a200c5de6f6d2f9a4b9e8c1d2f3a4b5c6d7e8f90
published_archive_sha256: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Los hashes anteriores solo muestran el formato. Un manifiesto real debe usar los resúmenes completos reales, con una firma nueva sobre el manifiesto o una etiqueta de lanzamiento firmada que lo contenga. No pongas el hash únicamente en la misma página web que aloja la descarga. Un atacante que pueda sustituir el archivo quizá también pueda sustituir esa página.

La receta de compilación debe indicar más que el compilador. Debe identificar la versión de Xcode, el SDK seleccionado, la arquitectura, el método de resolución de dependencias, la configuración de compilación, las herramientas de generación de código, las variables de entorno que afectan a la salida y el comando usado para empaquetar el archivo. Si el lanzamiento requiere un complemento privado del compilador o un binario descargado manualmente, dilo. El silencio convierte una entrada ausente en un callejón sin salida para cualquier verificador externo.

Los desarrolladores pueden comprobar la relación con el código fuente usando las herramientas habituales de Git:

git fetch origin tag v1.2.3
git tag -v v1.2.3
git rev-list -n 1 v1.2.3
git show -s --format=%H v1.2.3

El primer comando muestra el objeto de la etiqueta y si Git pudo validar su firma con una clave pública de confianza local. Los dos últimos comandos deberían mostrar el mismo hash completo del commit que registra el manifiesto. Una firma válida de una clave desconocida no basta. Los equipos necesitan una lista documentada de huellas digitales de las claves de firma de lanzamientos, mantenida bajo revisión, o solo habrán trasladado la confianza a un llavero local oculto.

La firma de macOS cambia los bytes después de compilar

Los desarrolladores de macOS deberían tratar la compilación, la firma, la notarización y el empaquetado como fases separadas, porque cada una puede modificar el artefacto.

Un paquete de aplicación contiene más de un ejecutable. Puede incluir un ejecutable principal, frameworks integrados, ayudantes de inicio de sesión, ayudantes de línea de comandos, metadatos, recursos y permisos. La herramienta codesign registra firmas en toda esa estructura. Firmar después de una copia final puede modificar el contenido, y un ticket de notarización puede quedar adherido más tarde al paquete o al instalador. Una herramienta de creación de imágenes de disco también puede codificar marcas de tiempo y decisiones sobre la disposición del sistema de archivos.

Aquí los equipos cometen un error evitable: firman durante el único comando de compilación y después esperan que un equipo externo reproduzca el archivo final. El verificador externo no tiene la credencial privada de firma, no debería tenerla y producirá naturalmente una firma distinta. La diferencia no demuestra nada sobre el programa compilado.

Crea primero un artefacto de comparación sin firmar. Archívalo con un método determinista cuando sea posible, calcula los hashes de su ejecutable y de sus recursos importantes y pasa después a una fase de firma exclusiva del lanzamiento. Conserva el artefacto sin firmar para verificadores independientes designados, aunque no lo publiques para todos los usuarios finales. Si la política de lanzamiento impide publicarlo, publica un manifiesto firmado con los hashes de sus componentes y deja que una segunda parte de confianza conserve el artefacto.

Inspecciona la aplicación firmada como una tarea de verificación independiente:

codesign -dv AppName.app 2\u003e\u00261
codesign -d --entitlements :- AppName.app 2\u003e/dev/null
spctl -a -vv AppName.app

El comando de permisos imprime el plist que macOS evaluará. Revísalo como código, no como decoración. Una extensión de red inesperada, un permiso de automatización, una autorización para depuración o un identificador de aplicación modificado pueden tener más consecuencias que un archivo de icono cambiado. El comando de evaluación informa de la cadena de autoridad y del resultado de la política en el Mac local.

El comando anterior incluye una opción con dos guiones solo porque codesign exige esa sintaxis. No hay una forma abreviada equivalente. El artículo no debería ocultarlo, pero el comando formal es una excepción técnica a la tipografía del texto. En tu propia documentación de lanzamientos, incluye el comando exactamente y captura su salida junto con el manifiesto.

Una aplicación universal requiere una comprobación adicional. Inspecciona cada arquitectura por separado en lugar de tratar el contenedor como una prueba:

lipo -info AppName.app/Contents/MacOS/AppName
shasum -a 256 AppName.app/Contents/MacOS/AppName

El primer comando informa de arquitecturas como arm64 y x86_64. El segundo produce una línea con el resumen SHA-256 y la ruta del archivo. Compila y compara cada objetivo de forma deliberada. Un lanzamiento puede tener una sección arm64 idéntica mientras que su sección x86_64 procede de otro conjunto de herramientas o de otro estado del código fuente.

Las dependencias y las rutas de compilación destruyen primero la reproducibilidad

Verifica el límite de acción
Sallyport ejecuta las acciones HTTP y SSH directamente y devuelve los resultados sin exponer el secreto subyacente.

Las salidas de compilación suelen divergir porque la compilación consumió una entrada no declarada, no porque el compilador tenga un misterioso fallo de no determinismo.

Los archivos de bloqueo ayudan, pero no resuelven el problema por sí solos. Un archivo de bloqueo puede registrar una versión, pero no el resumen del archivo. Un gestor de paquetes puede descargar un complemento del compilador, regenerar un grafo de paquetes o consultar un registro durante la compilación. Una dependencia binaria puede haberse recompilado con la misma etiqueta de versión. Si un cliente de agente usa generación de código, el propio generador es una entrada que necesita control de versiones y verificación.

Empieza por convertir la adquisición de dependencias en una fase independiente y registrada. Captura las sumas de comprobación de los archivos de paquetes, frameworks incluidos, entradas de código generado y herramientas descargadas. En proyectos de larga duración, conserva una caché interna de artefactos o un archivo de lanzamiento con esos materiales. Una URL de dependencia es una ubicación, no una identidad inmutable.

Las rutas de compilación son la segunda causa frecuente. La información de depuración puede incluir rutas absolutas. Los archivos generados pueden incluir el nombre de usuario actual, el directorio temporal, la configuración regional, la zona horaria o la fecha actual. Las herramientas de archivo pueden ordenar los archivos según la enumeración del sistema. Un compilador puede insertar un identificador de compilación basado en datos aleatorios.

Configura un entorno controlado en la receta documentada. El soporte exacto de cada variable depende del lenguaje y de las herramientas, pero el método de investigación no cambia:

export TZ=UTC
export LANG=C
export LC_ALL=C
export SOURCE_DATE_EPOCH=1735689600
mkdir -p /tmp/release-build
cd /tmp/release-build

SOURCE_DATE_EPOCH es la convención documentada por reproducible-builds.org para proporcionar a las herramientas una marca de tiempo estable. Solo funciona cuando las herramientas la respetan. No escribas la variable en un script de shell y des por hecho que funciona. Demuéstralo compilando en directorios distintos y comparando las salidas.

He visto equipos perder días examinando hashes diferentes cuando la única diferencia era un archivo de código generado que contenía una ruta del espacio de trabajo. Cambiaron las opciones del compilador, recompilaron dependencias y finalmente encontraron la ruta en una cadena de diagnóstico. Una herramienta de comparación binaria lo habría mostrado en minutos. Empieza por los bytes diferentes y rastrea después la entrada que los produjo. Adivinar a partir de los scripts de compilación es más lento y mucho menos fiable.

Compila dos veces y clasifica cada diferencia

Dos compilaciones limpias deberían producir una coincidencia o un conjunto pequeño y explicable de diferencias. Trata las diferencias sin explicación como defectos del lanzamiento, incluso si la aplicación parece funcionar con normalidad.

Ejecuta la receta en directorios de trabajo separados y, cuando sea posible, con cuentas de usuario separadas. El primer par detecta contaminación causada por la hora, las rutas y las cachés. Un segundo equipo con las mismas versiones documentadas de macOS y Xcode comprueba si la receta depende de un estado local accidental. Desactiva el acceso a la red después de preparar las dependencias. Si la compilación falla sin red, existe una descarga oculta o un paso de generación no documentado.

Compara por capas. Empieza con los hashes del ejecutable, continúa con las firmas de código, los permisos, los archivos de recursos y termina con el archivo exterior. Este orden evita que una marca de tiempo de la imagen de disco te distraiga de un ejecutable modificado.

Una pequeña comprobación de shell hace que el primer resultado sea inequívoco:

shasum -a 256 build-a/AppName.app/Contents/MacOS/AppName
shasum -a 256 build-b/AppName.app/Contents/MacOS/AppName
cmp -s build-a/AppName.app/Contents/MacOS/AppName build-b/AppName.app/Contents/MacOS/AppName
printf '%s\\n' $?

Las dos primeras líneas deben mostrar el mismo resumen. cmp devuelve cero cuando los archivos coinciden, y la última línea muestra 0 en ese caso. Un resultado distinto de cero significa que el ejecutable difiere. No reduzcas ese resultado a una insignia de aprobado o suspendido en un panel. Conserva ambos archivos e inspecciona la diferencia byte a byte con una herramienta de comparación binaria adecuada.

Clasifica cada diferencia en uno de cuatro grupos: metadatos de lanzamiento previstos, filtración del entorno, salida no determinista de una herramienta o desconocida. El grupo desconocido debe seguir visible. Los equipos se meten en problemas cuando añaden una exclusión amplia, como ignorar todos los archivos plist o todas las firmas, para que la comparación aparezca en verde. Las exclusiones deben nombrar el campo concreto que se espera que cambie y explicar por qué.

Un registro de fallo útil incluye los dos hashes de commit del código fuente, los comandos exactos de compilación, las versiones de las herramientas, una lista de los archivos diferentes y la explicación o referencia al problema de cada diferencia permitida. Ese registro forma parte de la ingeniería de lanzamientos, no es una nota privada en el historial del terminal de una persona.

La rutina de verificación debe funcionar con lanzamientos descargados

Conserva las pruebas de cada llamada
El registro de actividad documenta cada llamada dentro del mismo historial de auditoría cifrado.

Quien descarga un lanzamiento necesita un camino breve de verificación que separe la integridad del archivo, la identidad del editor y la correspondencia con el código fuente.

Primero verifica el resumen del archivo frente a un manifiesto firmado obtenido por un canal independiente. En macOS, shasum ya está disponible:

shasum -a 256 AppName-1.2.3.dmg

Compara carácter por carácter el resumen mostrado con el del manifiesto. Después inspecciona la aplicación montada con codesign y spctl para confirmar la autoridad de firma esperada y que macOS acepta el paquete. Estas comprobaciones protegen contra una descarga dañada o sustituida, pero todavía no demuestran su correspondencia con el código fuente.

Para esa afirmación final, el verificador obtiene la etiqueta de código fuente firmada, comprueba quién la firmó, sigue la receta de compilación declarada y compara la salida sin firmar indicada o el resumen del ejecutable. Un proyecto puede facilitar mucho este proceso publicando un script de verificación, pero los scripts deben ser legibles y pequeños. Un script de lanzamiento de mil líneas que descarga media Internet no es un mecanismo de verificación. Es otro sistema de compilación opaco.

Mantén proporcionado el camino para los usuarios habituales. La mayoría verificará un manifiesto de lanzamiento firmado y la firma de la aplicación. Los mantenedores, equipos de seguridad y revisores independientes deberían realizar compilaciones de determinados lanzamientos o antes de una distribución amplia. El objetivo es que las comprobaciones profundas sean posibles y rutinarias para quienes tienen esa responsabilidad.

No confundas una auditoría de actividad con la verificación de un artefacto. Sallyport puede verificar sin conexión la cadena de hashes de su historial de auditoría cifrado con sp audit verify, lo que indica si se han alterado las acciones registradas del agente. La reproducibilidad del lanzamiento responde a otra pregunta: si el cliente instalado corresponde al código fuente y a la receta que declaran sus mantenedores.

La procedencia de CI es una prueba, no un sustituto de las recompilaciones

Protege las claves de alto riesgo
Exige un clic o Touch ID cada vez que se use una clave sensible.

La procedencia de CI registra dónde se ejecutó un trabajo de compilación y qué entradas declaradas utilizó. Ayuda a los investigadores, pero no puede demostrar por sí sola que la salida del trabajo coincide con el código fuente revisado.

El modelo de procedencia de SLSA distingue de forma útil entre un artefacto y las declaraciones sobre cómo lo produjo un sistema de compilación. Una declaración de procedencia firmada puede vincular el resumen de un artefacto con una definición de compilación y una revisión del código fuente. Es una prueba sólida si confías en el repositorio, la identidad de CI, el aislamiento del ejecutor y los permisos de lanzamiento. Aun así, te pide confiar en quien compila.

Una compilación independiente cambia el modelo de confianza. Pregunta si un equipo separado, controlado por otra persona, puede ejecutar la receta pública y obtener la misma salida comparable. Cuando la procedencia y la reproducción independiente coinciden, un atacante debe comprometer más que una página de lanzamiento o un entorno de CI para ocultar un ejecutable sustituido.

Publica la procedencia con suficiente detalle para inspeccionarla: revisión del código fuente, revisión de la definición de compilación, identificador de la imagen del ejecutor, hashes de las dependencias, parámetros de los comandos y resumen de la salida. Evita declaraciones vagas que solo digan que un flujo terminó correctamente. Un flujo correcto puede compilar la rama equivocada, consumir una dependencia mutable o cargar un archivo desde un espacio de trabajo obsoleto.

CI también necesita separación de responsabilidades. La identidad que puede modificar el código fuente no debería recibir automáticamente acceso a la credencial privada de firma del lanzamiento. El trabajo que empaqueta una aplicación no debería recuperar en silencio un secreto de firma antes de que los revisores aprueben el commit de lanzamiento. Estos controles no hacen reproducible un binario, pero reducen la posibilidad de que una sola cuenta comprometida modifique a la vez el código fuente, la compilación y la distribución.

Incluye la verificación en el contrato de lanzamiento

Los equipos consiguen lanzamientos reproducibles cuando convierten la verificación en una salida prevista del lanzamiento, no en un proyecto de investigación que alguien intenta después de un incidente.

Empieza con un objetivo de lanzamiento y consigue que el ejecutable sin firmar se repita en dos directorios limpios. Registra cada entrada que descubras, especialmente el código generado y las dependencias binarias. Después publica la etiqueta firmada, la receta de compilación, el manifiesto, los hashes de salida, los metadatos de firma y cualquier diferencia permitida. Repite la comprobación en CI, pero conserva un camino para que un equipo externo haga el mismo trabajo.

No prometas identidad de bytes para archivos que tu proceso modifica deliberadamente después de la compilación comparable. Indica claramente el límite. Los lectores pueden trabajar con una afirmación honesta sobre un paquete sin firmar y con una fase de firma comprobada por separado. No pueden trabajar con una afirmación amplia que se deshace cuando aparece el primer hash diferente.

La primera prueba difícil es sencilla: toma el próximo lanzamiento candidato, compílalo con una cuenta nueva y compara el ejecutable antes de firmarlo. Si el resultado difiere, sigue investigando hasta poder nombrar los bytes, la entrada que los creó y si esa entrada debe formar parte de la receta documentada. Esa disciplina convierte un cliente de agente descargado en algo que el equipo puede inspeccionar, en lugar de limitarse a confiar en él.

FAQ

¿La firma de código demuestra que una aplicación descargada procede de su código fuente público?

Una aplicación de macOS firmada indica qué Developer ID firmó el paquete entregado y si los cambios posteriores invalidaron esa firma. No demuestra que un commit público concreto haya producido el ejecutable. Para hacer esa afirmación necesitas una referencia al código fuente, una receta de compilación exacta y un procedimiento de comparación.

¿Las compilaciones reproducibles siempre requieren paquetes de aplicación idénticos?

No. Una coincidencia byte por byte ofrece la evidencia más clara, pero no siempre es viable en paquetes firmados de macOS, porque la firma y la notarización modifican los archivos después de la compilación. Un objetivo práctico es conseguir una coincidencia documentada y explicable del ejecutable y los recursos antes de la firma de lanzamiento, y verificar por separado los metadatos de firma.

¿Debemos compilar desde una rama o desde una etiqueta de lanzamiento?

Verifica primero la firma de la etiqueta, inspecciona el commit que identifica y comprueba que el manifiesto de lanzamiento señala el mismo commit. Una rama protegida ayuda a colaborar, pero no constituye una prueba criptográfica de lo que publicó un mantenedor. Trata la etiqueta anotada y firmada como la referencia del código fuente del lanzamiento.

¿Por qué difieren dos aplicaciones de macOS firmadas después de la misma compilación?

La firma de Apple añade un CodeDirectory, datos de firma, información de la cadena de certificados y, a menudo, una marca de tiempo al paquete. Estos registros dependen de la identidad y del momento de la firma, por lo que las copias firmadas de forma independiente suelen diferir. Cuando sea posible, compara las salidas sin firmar y después inspecciona cada paquete firmado por separado.

¿Basta un archivo de bloqueo de dependencias para conseguir compilaciones reproducibles?

Un archivo de bloqueo solo reduce la ambigüedad si la compilación lo aplica realmente y cada artefacto descargado tiene un resumen criptográfico. Los registros de paquetes pueden eliminar o modificar paquetes, y algunos gestores resuelven metadatos durante la compilación. Para los lanzamientos que otros deban reproducir años después, archiva las dependencias o usa una caché con sumas de comprobación verificadas.

¿Puedo verificar una compilación en mi propio Mac?

Usa una cuenta limpia de macOS o una máquina virtual desechable, instala la versión documentada de Xcode, obtén la etiqueta de código fuente firmada y ejecuta el comando publicado. Desactiva la red después de preparar las dependencias. Compara los hashes del ejecutable resultante e inspecciona las diferencias antes de aceptar una coincidencia parcial. Compilar dos veces en el mismo portátil es una primera prueba útil, pero no revela entradas específicas del equipo anfitrión.

¿Cuál es la diferencia entre una SBOM y la procedencia de una compilación?

No. Una lista de materiales de software enumera componentes, mientras que la procedencia registra dónde y cómo se ejecutó una compilación. Ambas ayudan a investigar, pero ninguna demuestra que la salida sea reproducible si una parte independiente no puede volver a ejecutar la receta y comparar el resultado.

¿Qué archivos debo comparar en un lanzamiento de una aplicación de macOS?

Vuelve a compilar primero el ejecutable, porque es el código que se ejecuta. Después compara los datos de aprovisionamiento integrados, los permisos, los binarios auxiliares, los archivos de recursos y el manifiesto del actualizador, si la aplicación tiene uno. Una imagen de disco exterior coincidente ofrece pruebas más débiles, porque el empaquetado puede cambiar sin modificar el ejecutable.

¿La procedencia de CI puede sustituir una compilación independiente?

No. El servidor puede dar fe de su propio trabajo, pero no elimina la necesidad de confiar en el entorno de compilación, los permisos del repositorio, las fuentes de dependencias o quien publica el lanzamiento. Las compilaciones independientes ofrecen una línea de evidencia separada y suelen revelar errores que CI conservó sin llamar la atención.

¿Qué debemos hacer cuando una compilación reproducida no coincide?

Trata la diferencia como una investigación, no como una razón para cambiar el hash esperado hasta que coincida. Registra el commit de origen, las versiones de las herramientas, la arquitectura del equipo, los resúmenes de las dependencias y los archivos exactos que difieren. Si la diferencia procede de una fase deliberada de firma o empaquetado, sepárala de la salida comparable y documéntala.

Sallyport

Sallyport ejecuta llamadas de API y comandos SSH por tu agente de IA. Las claves se quedan en una bóveda local de tu Mac; tú apruebas cada ejecución y cada acción queda en un registro sellado.

© 2026 Sallyport · Código abierto bajo Apache-2.0 · Oleg Sotnikov