# Firma de código para agentes de IA: aprueba sesiones con pruebas

Un aviso de autorización que solo dice «el agente de IA solicita acceso» pide a una persona que dé su visto bueno a un misterio. En una máquina de desarrollo compartida, así es como alguien termina aprobando un script copiado, un terminal olvidado o un proceso iniciado por la persona equivocada. La pregunta útil es más concreta: ¿qué proceso ejecutable lo solicita, quién lo firmó, cómo llegó hasta aquí y qué puede hacer durante esta ejecución?

La firma de código aporta pruebas para tomar esa decisión. Puede vincular un programa en ejecución con una autoridad de firma y mostrar si el contenido firmado ha cambiado. No puede decirte si el agente recibió un prompt malicioso, si un editor de confianza publicó una versión defectuosa o si la acción de producción solicitada tiene sentido. Los equipos se meten en problemas cuando confunden una firma con una garantía de comportamiento.

En un Mac compartido, usa la autoridad de firma para reconocer clientes de agente conocidos, rechazar sorpresas y hacer que cada autorización caduque junto con el proceso que la obtuvo. Combínala con una frontera clara entre cuentas, credenciales de alcance limitado y registros que permitan reconstruir tanto la autorización como la llamada posterior.

## Una firma identifica el código, no la intención que hay detrás

Una firma de código puede demostrar quién firmó una pieza concreta de código y si macOS todavía puede verificar su contenido firmado. No demuestra que el código merezca acceso a tus sistemas. Esta diferencia debe mantenerse visible en cada flujo de autorización.

La documentación de firma de código de Apple, la nota técnica TN2206, describe las firmas como una forma de validar código y expresar un requisito designado que macOS puede usar para reconocer posteriormente el mismo código. El requisito designado importa porque es más preciso que un nombre de archivo. Un ejecutable llamado `agent` puede copiarse en cualquier lugar y cambiar de nombre. Su identidad firmada conserva mejor la continuidad si la cadena de firma y el requisito siguen siendo válidos.

Esa continuidad responde a una pregunta práctica: «¿Es este el cliente que acordamos permitir?». No responde a estas otras preguntas, igual de prácticas:

- ¿Recibió el agente instrucciones que nunca deberían llegar a producción?
- ¿Inició alguien este proceso de forma deliberada, desde el directorio de proyecto esperado?
- ¿Tiene el proceso una extensión, un complemento o una configuración que cambie su comportamiento?
- ¿Corresponde la llamada a la API solicitada a esta tarea?
- ¿Tiene la credencial usada en la llamada más permisos de los que necesita la tarea?

A menudo se recurre al nombre del editor como si fuera un veredicto. No lo es. Una autoridad de firma te dice quién controlaba la credencial de firma utilizada para ese artefacto. Un editor grande puede firmar muchos programas. Un equipo interno pequeño puede firmar una compilación perfectamente adecuada. Tu decisión de autorización debe comparar la identidad observada con una lista de permitidos que tu equipo pueda explicar, no con la vaga sensación de que el emisor resulta familiar.

También hay un límite fácil de pasar por alto: la firma verifica el código que se firmó. No cubre automáticamente todo lo que un proceso lea después. Los archivos de configuración, los prompts, las variables de entorno, los datos del repositorio, las extensiones descargadas y las respuestas remotas pueden cambiar lo que hace un programa correctamente firmado. Si apruebas un agente porque su binario te resulta familiar, todavía necesitas controles sobre sus acciones.

## Lee una tarjeta de autorización como un registro de atribución

Una tarjeta de autorización debe ofrecer al operador suficiente información para atribuir una solicitud a un proceso real antes de aprobarla. La autoridad de firma debe aparecer arriba porque es más difícil de falsificar que la etiqueta de un proceso, pero tiene que estar junto a la ruta del proceso y los datos de la sesión.

Para un proceso que solicita acceso en una máquina compartida, quiero ver estos datos en un mismo lugar:

- La identidad del ejecutable o de la aplicación y su ruta local completa.
- La autoridad de firma o el requisito designado utilizado para reconocerlo.
- El ID del proceso y el proceso padre, para saber qué lo inició.
- La cuenta de usuario de macOS que lo posee.
- El canal de acción y el destino, como un host de API o un host SSH.

Los tres primeros datos detectan fallos distintos. Un nombre visible familiar con una ruta inesperada suele indicar un binario copiado o un envoltorio. Una ruta familiar con una autoridad desconocida suele indicar que alguien lo recompiló, lo sustituyó o hizo que un enlace simbólico apuntara a otro lugar. Un ejecutable conocido iniciado por un proceso padre inesperado puede significar que otra herramienta de automatización lo inició en lugar del desarrollador que está viendo el aviso.

En un Mac compartido, la cuenta de usuario no es un adorno. Si dos ingenieros comparten un mismo inicio de sesión, una autorización dice muy poco sobre qué persona inició el agente. La máquina todavía puede decirte qué proceso hizo la llamada, pero el equipo ha perdido una frontera humana clara antes de que empiece el flujo de autorización. Las cuentas separadas de macOS cuestan menos que discutir sobre el historial del terminal después de un incidente.

No enseñes a la gente a aprobar basándose solo en un logotipo, un nombre corto de comando o una cadena de autoridad. Enséñales a reconocer una combinación completa y esperada: cliente de agente aprobado, autoridad de firma esperada, ubicación local prevista, su propia cuenta y un destino relacionado con la tarea. Una tarjeta que omite la mayor parte de esas pruebas convierte una autorización de un clic en una suposición.

## Inspecciona el ejecutable antes de convertirlo en una identidad aprobada

Debes inspeccionar la aplicación o el ejecutable exacto que tu equipo piensa aprobar antes de que alguien dependa de su autoridad de firma en un flujo real. Hazlo durante la configuración, registra el resultado esperado en el manual interno y repite la comprobación cuando actualices deliberadamente el cliente.

En macOS, `codesign` puede mostrar los detalles de la firma. Su salida detallada va a la salida de error estándar, así que redirígela si quieres guardar un registro de revisión:

```sh
codesign -dv --verbose=4 /Applications/ApprovedAgent.app 2\u003e\u00261
```

La salida suele incluir campos como estos:

```text
Executable=/Applications/ApprovedAgent.app/Contents/MacOS/ApprovedAgent
Identifier=com.example.approved-agent
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20500 size=...
Authority=Developer ID Application: Example Developer (ABCDE12345)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
TeamIdentifier=ABCDE12345
Sealed Resources version=2 rules=13 files=...
```

Conserva juntos `Identifier`, la `Authority` de la hoja y `TeamIdentifier`. El Team ID por sí solo es una regla de aprobación deficiente porque una organización puede firmar varias aplicaciones. El identificador por sí solo es más débil porque alguien puede crear un programa sin firma con el mismo identificador de paquete. La cadena es lo que hace útil la afirmación.

Después, verifica el contenido firmado:

```sh
codesign --verify --deep --strict --verbose=2 /Applications/ApprovedAgent.app
```

Un resultado correcto suele ser silencioso. Un fallo identifica un componente anidado alterado u otro problema de firma. `--deep` pide a `codesign` que recorra el código anidado. Es útil como ayuda de inspección, pero no lo trates como una prueba de que cada componente incluido cumple tu política de seguridad. Apple documenta que la verificación profunda se aplica de forma recursiva y puede ocultar el hecho de que el diseño de firma interno de un paquete merece una revisión directa.

Para una aplicación obtenida fuera de tu canal de software gestionado, pide también a Gatekeeper que la evalúe:

```sh
spctl --assess --type execute --verbose=4 /Applications/ApprovedAgent.app
```

`spctl` y `codesign` responden preguntas relacionadas, pero diferentes. `codesign` verifica las firmas frente al artefacto. `spctl` pregunta si la política de evaluación del sistema lo acepta. Una evaluación correcta es una señal útil de procedencia. No significa que los comandos, scripts o comportamientos remotos de la aplicación sean seguros para producción.

Registra la ruta que revisaste. Si alguien aprueba después `/Users/alex/bin/agent` porque su etiqueta se parece a la de la aplicación revisada en `/Applications`, no ha repetido esta comprobación. La ruta forma parte de las pruebas.

## La firma de un intérprete no avala el script que ejecuta

Un terminal, un entorno de ejecución o un shell firmado no puede responder por cualquier script que se le entregue al iniciarse. Esta es la brecha que hay detrás de muchas autorizaciones que parecen razonables al hablar de ellas, pero fallan en la práctica.

Imagina a un desarrollador que inicia un agente con un comando como este:

```sh
/usr/bin/python3 /Users/dev/work/demo/tools/agent_runner.py
```

El Python del sistema puede tener una firma conocida. Ese hecho te informa sobre el binario del intérprete. No dice nada sobre `agent_runner.py`, los archivos que importa del repositorio, el archivo `.env` que lee ni las instrucciones que recibe por la entrada estándar. Si la interfaz de autorización identifica solo `python3`, un atacante necesita cambiar el script o el estado del proyecto, no el intérprete.

El mismo problema aparece con `node`, los shells, las extensiones de editores y los ejecutores de automatización genéricos. Una regla amplia como «aprobar procesos firmados por este editor del entorno de ejecución» facilita la aprobación de comportamientos que nadie revisó. Es popular porque reduce la fricción de las autorizaciones. Es incorrecta para cualquier canal que pueda llegar a credenciales importantes.

Usa uno de estos dos modelos y deja claro cuál eligió tu equipo. El modelo más sólido aprueba un cliente de agente firmado y creado para ese fin, cuyo proceso de sesión es el programa que solicita acceso. El modelo más flexible permite intérpretes, pero trata cada inicio de script como una sesión distinta y muestra junto a la autoridad del intérprete la ruta del script, el directorio del proyecto, los argumentos y el proceso padre.

Puedes inspeccionar el contexto básico de un proceso en ejecución con herramientas estándar:

```sh
ps -p 4821 -o pid=,ppid=,user=,command=
ps -p 4812 -o pid=,ppid=,user=,command=
```

El primer comando podría mostrar el proceso del agente y el segundo, su proceso padre. Compara la línea de comandos con el trabajo del desarrollador. Si el hijo procede de un terminal situado en el proyecto esperado, las pruebas encajan. Si procede de un programador desatendido, un asistente del navegador u otro agente, deja de tratar la solicitud como una autorización rutinaria del desarrollador.

Para un cliente basado en scripts, incluye el resumen criptográfico del script en el registro de autorización. Una comprobación local sencilla basta para hacer visibles los cambios:

```sh
shasum -a 256 /Users/dev/work/demo/tools/agent_runner.py
```

Un resumen no hace fiable un script. Ofrece a tu equipo una respuesta concreta cuando alguien pregunta si el script aprobado cambió entre ejecuciones. Guarda el resumen esperado solo para una versión revisada o un estado controlado del proyecto. No conviertas en un ritual copiar hashes desde mensajes de chat.

## Las máquinas compartidas necesitan límites de cuenta antes que reglas de autorización

Un Mac de desarrollo compartido se puede gestionar cuando cada persona usa una cuenta independiente y cada ejecución del agente tiene un responsable claro. Si todo el mundo usa el mismo inicio de sesión, la autoridad de firma no puede reparar la falta de atribución.

Crea cuentas independientes de macOS para cada desarrollador y evita usar a diario una cuenta de administrador común. El proceso del agente debe ejecutarse con la cuenta de la persona que lo inició. Así, sus archivos de proyecto, historial del terminal, variables de entorno y decisiones de autorización tendrán un responsable real. Los repositorios compartidos no requieren cuentas compartidas del sistema operativo.

Una configuración práctica también separa los destinos sensibles. Usa entradas de credenciales distintas para desarrollo, staging y producción, con etiquetas que indiquen claramente la intención al operador. Una autorización para `inventory-staging` no debería seleccionar silenciosamente la credencial de producción porque ambas apuntan al mismo cliente de API. Si el nombre de la credencial oculta el entorno, la persona no puede elegir bien cuando más importa.

El acceso físico también importa. Alguien frente a un Mac compartido desbloqueado puede iniciar un proceso con la cuenta activa y esperar a que el propietario haga clic en un aviso de autorización. Bloquea la pantalla al ausentarte, exige un inicio de sesión nuevo después de la suspensión y evita dejar un terminal privilegiado abierto en un espacio común. Son controles cotidianos, por eso los equipos los omiten hasta que tienen que limpiar un problema evitable.

No resuelvas el riesgo de una máquina compartida publicando una lista enorme de autoridades de firma aprobadas. Esa lista tiende a crecer hasta incluir editores, entornos de ejecución, gestores de paquetes, herramientas de compilación y aplicaciones auxiliares. Para entonces, solo dice que la máquina se usa para desarrollar. Mantén reducido el conjunto aprobado para los agentes que pueden solicitar acciones externas y documenta por qué pertenece allí cada identidad.

## La autorización de una sesión debe vincularse a un proceso, no a una persona para siempre

Una autorización de sesión debe permitir un proceso de agente observado durante el tiempo que ese proceso exista y caducar cuando termine. Es un punto medio útil entre obligar a decidir ante cada solicitud inofensiva y conceder un permiso permanente que sobreviva al trabajo.

El límite del proceso importa más que un tiempo de espera del calendario. Un agente que termina y se reinicia crea un contexto de ejecución nuevo. Puede tener otro directorio de trabajo, un binario modificado, extensiones distintas, otro proceso padre o una persona diferente frente al teclado. Exigir una nueva autorización al reiniciarse ofrece al operador otra oportunidad de detectar esos cambios.

Aquí es donde la firma de código resulta útil. El flujo de autorización puede mostrar primero la autoridad porque ayuda al operador a reconocer un cliente esperado, mientras que la vinculación con la sesión evita que ese reconocimiento se convierta en un permiso indefinido. Si el proceso del agente termina, la autorización debe desaparecer con él. Si el operador observa un comportamiento sospechoso, necesita una forma inmediata de revocar la sesión antes de investigar en detalle la firma del código.

Mantén separadas la autorización y la autenticación. Touch ID o una contraseña pueden demostrar que el usuario de macOS presente aprobó la acción. No identifican el proceso. La firma de código puede ayudar a identificar el proceso. Ninguna de las dos decide si el destino y la acción son adecuados. Una buena tarjeta de autorización presenta los tres tipos de pruebas en lugar de fingir que son intercambiables.

Para el trabajo habitual en un repositorio, una decisión de sesión puede cubrir operaciones de lectura repetidas contra una API de desarrollo. Para una operación que cambie la configuración de un despliegue, rote credenciales, elimine registros o abra una conexión SSH con un host de producción, exige una decisión nueva para esa llamada. La fricción debe aparecer cuando cambia la consecuencia, no al azar cuando expira un temporizador.

## La autoridad de firma no detiene los fallos que la gente espera que detenga

Una cadena de firma válida no puede impedir que un cliente de confianza reciba entradas maliciosas, que una cuenta de desarrollador comprometida firme código malicioso o que un proceso aprobado haga una solicitud imprudente. Trátalos como vías de fallo distintas y coloca delante de cada una el control adecuado.

La primera vía es el ataque mediante prompts o instrucciones del repositorio. Un asistente de código lee un comentario malicioso que le indica extraer un archivo de configuración mediante una solicitud HTTP. El ejecutable puede ser exactamente el cliente aprobado y estar correctamente firmado. La autorización debe mostrar el destino y el canal solicitado, porque la firma no aporta ninguna prueba sobre la instrucción que siguió.

La segunda vía es una actualización legítima que tu equipo no ha revisado. Un editor puede firmar una nueva versión con la misma autoridad. Si apruebas cualquier versión futura de esa autoridad sin inspeccionar su identidad y su origen, has convertido la propiedad del editor en toda tu política. Puede ser aceptable para herramientas locales de bajo riesgo. No basta para un agente que puede utilizar credenciales de producción.

La tercera vía es la manipulación de procesos locales. Una aplicación firmada puede cargar un complemento, heredar una variable de entorno o ejecutarse con un proceso padre que suministre argumentos inesperados. Las protecciones de macOS reducen algunas formas de manipulación, pero un sistema de autorización todavía debe mostrar el contexto real del proceso. Cuando las pruebas no coincidan, deniega la solicitud e inspecciona la máquina. No inventes una explicación benigna porque la cadena de autoridad te resulte familiar.

La cuarta vía es el exceso de privilegios. Un cliente correctamente identificado puede usar una credencial con permisos para hacer mucho más de lo que requiere la tarea. Limita las credenciales a la API, el host, el repositorio y el entorno que necesita el agente. La firma de código puede decirte qué cliente utilizó una credencial, pero no puede reducir sus permisos después de los hechos.

Por eso «firmado equivale a seguro» es una recomendación dañina. Suena sencilla y genera menos avisos. También fomenta autorizaciones sin destino, resumen de la acción ni límite de sesión. Una señal de firma ayuda a una persona a distinguir código conocido de código desconocido. Nunca debe borrar el resto de la decisión.

## La autorización por llamada pertenece a las credenciales irreversibles o de alto impacto

Exige una decisión humana para cada uso de una credencial cuando una solicitud puede producir una consecuencia que la autorización de sesión no debería permitir silenciosamente. El umbral es el impacto de la acción, no que el ejecutable del agente parezca fiable.

Usa autorización por llamada para credenciales que puedan escribir o eliminar datos de producción, cambiar identidades o permisos, crear compromisos externos, publicar software o entrar en un entorno SSH sensible. El operador debe ver la etiqueta de la credencial y el destino en el momento de usarla. Un mensaje genérico como «usar secreto» le obliga a recordar demasiado bajo presión.

Mantén utilizable el trabajo de bajo impacto. Un desarrollador que tenga que aprobar cada lectura de una API de pruebas aprenderá a hacer clic sin leer. Ese comportamiento anula el control y hace más fácil pasar por alto los avisos importantes. La autorización de sesión funciona bien cuando el agente realiza un trabajo repetitivo y limitado contra un destino de desarrollo y la identidad del proceso es la esperada.

La escala de decisiones debe ser lo bastante sencilla para que la gente pueda explicarla después de una semana difícil. Primero, un almacén de credenciales bloqueado deniega todas las acciones. Después, un proceso de agente nuevo necesita autorización de sesión. Por último, algunas credenciales requieren aprobación cada vez que se utilizan. No escondas estas decisiones en un lenguaje de políticas personalizado que solo una persona pueda interpretar. Las excepciones ocultas son el punto en que las reglas para máquinas compartidas empiezan a degradarse.

Sallyport aplica directamente este modelo de tres controles: un almacén bloqueado deniega las acciones, un proceso de agente nuevo solicita autorización de sesión por defecto y una credencial seleccionada puede requerir aprobación en cada uso. Su tarjeta de autorización muestra primero la autoridad de firma del proceso, que es el punto correcto para empezar cuando varios usuarios comparten un Mac.

## Audita la autorización y la llamada como eventos separados

Necesitas registros separados para las sesiones de los agentes y para las acciones individuales, porque ninguno de los dos puede responder por sí solo a todas las preguntas de un incidente. El registro de sesión explica qué proceso recibió autorización y cuándo terminó esa autorización. El registro de acción explica qué intentó hacer después de la aprobación, contra qué canal o destino y qué resultado obtuvo.

Una secuencia útil para investigar sería esta:

1. Busca el registro de sesión del proceso que solicitó acceso.
2. Comprueba la cuenta de usuario, la ruta del ejecutable, la autoridad de firma, el proceso padre y la hora de aprobación.
3. Busca las llamadas realizadas durante esa sesión y compara los destinos con la tarea asignada.
4. Revoca la sesión si sigue activa. Después, desactiva o rota la credencial afectada si las llamadas muestran un uso indebido.
5. Conserva los registros antes de cambiar los archivos del proyecto o reinstalar el cliente.

El orden importa. Los equipos suelen empezar leyendo el código y pierden las pruebas de lo que ocurrió realmente. Primero establece la secuencia de autorización y acción. Después inspecciona el ejecutable, el estado del repositorio, el historial del shell y la configuración relevante.

Las pruebas contra manipulaciones tienen valor en este contexto. Un registro de auditoría que un proceso local pueda reescribir ofrece poco consuelo cuando ese proceso forma parte del evento investigado. El encadenamiento de hashes da al verificador una forma de detectar alteraciones o eliminaciones dentro de la secuencia registrada, aunque no demuestra que se capturaran todos los eventos posibles. Sé preciso con ese límite. Las pruebas contra manipulaciones no lo saben todo.

Sallyport proyecta los diarios de sesiones y actividad desde un único registro de auditoría cifrado y encadenado mediante hashes, y `sp audit verify` comprueba la cadena sin conexión y sin necesitar una credencial del almacén. Así, la verificación rutinaria resulta práctica después de un incidente o antes de entregar los registros a otra persona para su revisión.

## Haz que las decisiones de autorización sean reproducibles, no personales

Un equipo debe poder explicar por qué una sesión concreta de agente obtuvo autorización sin depender de la memoria de la persona que hizo clic. Escribe un perfil breve de autorización para cada cliente de agente permitido y guárdalo cerca de las instrucciones operativas del repositorio.

El perfil debe indicar la ruta esperada de la aplicación o el ejecutable, el identificador, la autoridad de firma, el proceso padre habitual, las cuentas de usuario previstas, los entornos permitidos y las credenciales que requieren una decisión en cada llamada. No es burocracia por sí misma. Ofrece a un ingeniero nuevo un estándar observable y a la persona de guardia una forma de rechazar una solicitud extraña sin discutir sobre preferencias.

Revisa el perfil cuando cambie cualquiera de estos elementos: se actualice el cliente del agente, el equipo adopte un nuevo envoltorio de entorno de ejecución, una credencial obtenga permisos más amplios o un flujo que antes era local llegue a un servicio compartido. Si cambia la identidad de firma, detente y verifica el cambio mediante la fuente de software en la que confía tu equipo. No normalices una autoridad inesperada haciendo clic una vez y dejando la investigación para después.

Realiza un simulacro de fallo deliberado en el Mac compartido. Inicia el cliente aprobado desde la cuenta esperada y confirma la autoridad mostrada y el comportamiento de la sesión. Después, inicia un script no aprobado mediante un intérprete firmado, inicia el cliente desde otra cuenta y solicita una credencial marcada para aprobación por llamada. En cada caso, el comportamiento correcto debe resultar evidente para el operador. Si los avisos se parecen demasiado, mejora la información mostrada antes de que alguien se enfrente a un error real.

La firma de código es útil porque sustituye un nombre de proceso vago por pruebas que se pueden comprobar. Limita su función a eso. Aprueba el proceso conocido para el trabajo que tienes delante, mantén reducido el alcance de las credenciales y facilita la revocación de una sesión sospechosa mientras las pruebas todavía estén intactas.
