8 min de lectura

Acceso SSH para agentes de IA: comandos remotos sin claves privadas

El acceso SSH de los agentes de IA debe usar acciones remotas mediadas, no claves privadas copiadas. Configura aprobaciones, límites del servidor, verificación de hosts y registros de auditoría.

Acceso SSH para agentes de IA: comandos remotos sin claves privadas

Dar a un agente de programación con IA una clave privada SSH es una abstracción equivocada. El agente no necesita una credencial duradera que pueda autenticarse desde cualquier máquina en cualquier momento. Necesita permiso para realizar una acción remota concreta mientras tú puedas verla, detenerla y explicar qué ocurrió.

Parece un pequeño cambio de arquitectura. No lo es. Separa un secreto que puede viajar para siempre de una solicitud SSH que tiene un solicitante, un destino, un comando, un resultado y un responsable.

He visto equipos pasar días afinando las reglas de los prompts de un agente y dejar ~/.ssh/id_ed25519 legible para ese mismo proceso. Las reglas del prompt son decoración cuando la clave privada está disponible. Un comando de shell puede copiar el archivo, mostrarlo, archivarlo o enviarlo a un lugar que no descubrirás hasta dentro de semanas.

Una clave privada no es un token de API con un nombre más corto. Es un token de autoridad reutilizable para cada servidor SSH que acepte su parte pública.

Dale al agente una acción, no una identidad

Un agente debería solicitar una operación SSH, mientras que un componente confiable independiente conserva la identidad y establece la conexión. Ese componente recibe datos estructurados como el destino, la cuenta remota, el comando, los argumentos y el tiempo de espera. Comprueba la solicitud, se autentica en el servidor, captura el resultado y devuelve al agente únicamente ese resultado.

El secreto permanece en una sola máquina. Y lo más importante: el derecho a usarlo deja de seguir al proceso del agente allá donde vaya.

Esta diferencia cambia el modo en que se produce un fallo. Si un agente queda comprometido o sigue instrucciones maliciosas de un repositorio, todavía puede solicitar un comando peligroso. No puede exportar silenciosamente la clave privada y reutilizarla desde una máquina virtual desechable el mes que viene. Has reducido un problema abierto de robo de credenciales a un problema de autorización y control de comandos.

El segundo problema sigue siendo importante. La diferencia es que puedes gestionarlo.

Una estructura de solicitud útil resulta deliberadamente aburrida:

{
  "host": "deploy-01.internal.example",
  "user": "release",
  "command": "/usr/local/libexec/release-service",
  "args": ["api", "2025.03.08-4f2c1a7"],
  "timeout_seconds": 120
}

No envíes una cadena de shell como ssh deploy-01 'cd /srv/api && git pull && sudo systemctl restart api' a través de cinco capas y llames a eso control. Las reglas de análisis del shell pasan a formar parte de tu límite de seguridad, y casi nadie las revisa como tal. Mantén fija la ruta del comando, pasa los argumentos como valores separados y haz que el wrapper remoto rechace los valores que estén fuera de la gramática esperada.

Prefiero un contrato de acción algo incómodo de usar antes que un terminal remoto flexible que nadie pueda limitar. La incomodidad aparece durante la configuración. El daño de un terminal sin restricciones aparece después.

El intermediario debe devolver un resultado con una estructura suficiente para que el agente continúe sin adivinar:

{
  "exit_code": 0,
  "stdout": "released api version 2025.03.08-4f2c1a7\n",
  "stderr": "",
  "duration_ms": 1842
}

No devuelvas credenciales, sockets del agente, contenido de known_hosts ni un TTY interactivo. Son detalles de implementación del lado confiable.

Poseer, firmar y ejecutar son poderes distintos

Los equipos suelen hablar del «acceso SSH» como si describiera una sola cosa. En realidad, incluye al menos tres poderes muy diferentes: poseer una clave privada, pedir a un agente que cree una firma y hacer que un intermediario ejecute un comando remoto concreto.

Poseer la clave privada es la capacidad más amplia. Quien lea el archivo puede copiarlo indefinidamente y probarlo contra cualquier servidor accesible. Los permisos de archivo ayudan, el cifrado del disco ayuda y las frases de contraseña ayudan, pero ninguno responde a la pregunta central: ¿por qué un proceso de IA necesitaba una credencial portátil?

Un ssh-agent elimina la necesidad de que cada cliente lea un archivo de clave privada. El proceso puede solicitar una firma mediante SSH_AUTH_SOCK. Esto mejora la higiene del equipo local, pero firmar sigue concediendo capacidad de autenticación. El manual de OpenSSH ssh-agent(1) indica que el agente mantiene las claves privadas fuera del tránsito de red durante el reenvío, mientras que el solicitante reenviado recibe el resultado de las operaciones de identidad. Es una propiedad útil, pero no un modelo completo de autorización.

La ejecución de acciones es más limitada cuando se diseña así. Un intermediario puede rechazar un host desconocido, impedir el uso de otra cuenta remota, exigir una decisión humana, limitar el tiempo de ejecución, rechazar un TTY y conservar un registro de la llamada. También puede utilizar una identidad SSH distinta para cada clase de operación.

Este último detalle importa más de lo que los equipos esperan. Una sola identidad que pueda leer registros, desplegar código, editar /etc/sudoers y abrir túneles crea un límite de autorización tan grande como toda tu flota. Cuatro identidades con restricciones precisas en el servidor crean cuatro problemas más pequeños.

Prefiero rotar cuatro identidades limitadas después de un error que pasar un fin de semana demostrando que una identidad de administrador no llegó a todos los hosts.

Este patrón no convierte un comando peligroso en seguro. Te proporciona puntos donde detectarlo: antes de la conexión, durante la autenticación del servidor, dentro del comando remoto forzado y en el registro posterior.

El reenvío del agente SSH resuelve otro problema

El reenvío del agente SSH evita copiar una clave privada a un host de salto, pero no hace que una máquina remota sea segura para entregársela a un agente. El host remoto obtiene acceso a un socket que puede solicitar operaciones al agente de autenticación local.

OpenSSH lo dice claramente en ssh_config(5): el reenvío del agente debe habilitarse con precaución porque un usuario capaz de eludir los permisos del host remoto puede utilizar el agente local mediante la conexión reenviada. El atacante no puede extraer los bytes de la clave privada a través de esa interfaz, pero sí puede pedir a las identidades cargadas que se autentiquen.

La advertencia es aún más importante con las herramientas autónomas. Un agente puede conectarse a un host porque una tarea le pidió inspeccionar un registro. Una instrucción maliciosa del repositorio, una cuenta remota comprometida o un comando mal aislado pueden encontrar SSH_AUTH_SOCK y utilizar la capacidad de firma reenviada. La clave privada sigue siendo técnicamente secreta, pero la autoridad de autenticación se utiliza de forma indebida. A la víctima no le servirá de mucho esa distinción.

No actives ForwardAgent yes de forma global. Añade ForwardAgent no a la configuración base del cliente y crea una excepción explícita únicamente para un flujo de trabajo humano concreto que realmente la necesite.

Host *
    ForwardAgent no
    AddKeysToAgent no
    IdentitiesOnly yes
    StrictHostKeyChecking yes

Host legacy-bastion
    HostName bastion.internal.example
    User ops
    ForwardAgent yes

La excepción anterior todavía necesita un motivo, un responsable y una fecha de retirada. Una excepción permanente de reenvío tiende a volverse invisible porque SSH hace que todo funcione con demasiada facilidad.

Las identidades limitadas por destino mejoran la situación, pero no sustituyen un límite de acción. El manual de OpenSSH ssh-add(1) explica que las restricciones de destino comprueban toda la ruta de conexión cuando un cliente y un servidor compatibles reenvían el agente. También advierte que alguien con un SSH_AUTH_SOCK remoto puede reenviar de nuevo ese socket, aunque su uso siga limitado a los destinos permitidos.

Usa restricciones de destino cuando encajen. No las confundas con una política de comandos. Indican dónde puede autenticarse una identidad, no si debe ejecutarse rm -rf /srv/release-cache después de llegar allí.

Sigue el fallo a través de la ruta del comando

Un incidente plausible comienza con un atajo bien intencionado: un desarrollador coloca una clave privada de despliegue en una variable de entorno porque el agente de programación necesita ejecutar un solo comando de lanzamiento. El agente lee un issue del repositorio que incluye un comando de diagnóstico sugerido. El comando muestra el entorno para solucionar el problema y la transcripción de ejecución acaba en un registro de sesión local.

La primera pérdida ocurrió antes de SSH. La clave privada entró en un proceso que no necesitaba conservarla.

Ahora el agente tiene varias formas de filtrarla o reutilizarla. Puede escribir el valor en un archivo temporal. Puede enviarlo a un host remoto con scp. Puede incluirlo en un commit de Git. Puede entregarlo a un subproceso fuera de los límites que dabas por supuestos. Una clave privada copiada una vez no caduca solo porque detuviste la ejecución del agente.

Supón que el equipo usó el reenvío del agente en su lugar. La instrucción del repositorio indica al agente que se conecte a build-02 y después ejecuta un comando que expone el socket reenviado a un proceso local de esa máquina remota. El atacante no puede mostrar la clave privada, pero sí puede pedir al socket que se autentique en otro host con una identidad cargada en el agente del desarrollador. El reenvío nunca pretendió ser un mecanismo de delegación general, pero se convirtió en uno.

Ahora considera el diseño mediado. El agente envía una solicitud para release-service api 2025.03.08-4f2c1a7 en deploy-01. El intermediario ve que es la primera solicitud de un proceso de agente nuevo y pide autorización. La persona que aprueba ve la autoridad de firma de código del proceso solicitante, la identidad remota y el objetivo. El intermediario se conecta únicamente al host indicado. El servidor acepta solo una identidad de despliegue restringida y ejecuta un único wrapper del servidor.

La instrucción maliciosa todavía puede solicitar un lanzamiento. No puede convertir esa solicitud en un shell de inicio de sesión, un reenvío de puertos, una clave privada copiada ni un recorrido por servidores no relacionados.

Esto reduce mucho el alcance del daño, pero te quita flexibilidad. Un agente genérico puede improvisar ante estados extraños de producción. Una interfaz de acciones limitada no puede. Tendrás que añadir operaciones deliberadas para registros, estado del servicio, rollback, comprobaciones de migración y limpieza de artefactos. Alguien debe ser responsable de esas interfaces. Ese trabajo no es opcional; el SSH sin restricciones simplemente lo oculta.

La respuesta correcta es hacer que el camino seguro cubra las tareas que la gente realmente realiza, no reabrir un shell sin restricciones cada vez que al camino seguro le falte una función.

Pon el cliente SSH detrás de un punto de decisión local

Controla cada clave sensible
Configura una clave SSH para que requiera aprobación con un clic o Touch ID cada vez que se use.

Un punto de decisión local debe controlar tres cosas: la identidad privada cifrada, el permiso para usarla y las evidencias que produce al hacerlo. El agente no debería controlar ninguna de ellas.

Sallyport sigue este patrón con los agentes de macOS: su componente sp mcp incluido acepta llamadas MCP normales, mientras que la aplicación de la barra de menús guarda las identidades SSH en su bóveda cifrada y utiliza sp-ssh para realizar la conexión. El agente recibe el resultado del comando, no la credencial.

La estructura importa más que la implementación concreta:

AI agent process
    -> local action request
        -> authorization decision
            -> SSH helper using protected identity
                -> remote sshd and restricted account
                    -> stdout, stderr, exit status

Mantén el punto de decisión en la máquina administrada del desarrollador cuando una persona necesite supervisar el trabajo. No lo conviertas en un proxy de red que firme silenciosamente cada solicitud de todos los procesos. El límite del proceso local permite atribuir la llamada y rechazar un ejecutable inesperado antes de iniciar cualquier conexión de red.

La identidad del proceso no es un campo decorativo en una tarjeta de aprobación. Una solicitud de la aplicación firmada que esperabas es distinta de una solicitud de un binario sin firmar ejecutado desde /tmp, aunque ambos afirmen ser «el agente de programación». En macOS, la autoridad de firma del código ofrece al aprobador algo concreto que evaluar.

Quiero que un proceso nuevo obtenga una sesión antes de poder usar una identidad SSH. También quiero que esa sesión desaparezca cuando el proceso termine. Las concesiones de larga duración son fáciles de operar y difíciles de explicar después de un compromiso.

El bloqueo de la bóveda debe denegar todas las acciones SSH. No debe existir un fallback parcial a una clave privada en caché, un archivo PEM exportado ni un proceso auxiliar con su propia copia oculta. Si tu ruta de emergencia evita la protección, con el tiempo se convertirá en la ruta normal.

Haz que la cuenta remota sea aburrida a propósito

El servidor remoto debe limitar lo que puede hacer una autenticación SSH correcta. Una clave privada protegida es solo una parte del control; el servidor debe tratar esa identidad como algo creado para un propósito concreto y no como una cuenta de administrador humano.

Crea una cuenta Unix independiente para la acción, como release, diagnostics o backup. No le des un perfil personal de shell, un directorio personal amplio ni acceso mediante contraseña. No coloques su identidad pública junto a la identidad personal sin restricciones de un ingeniero en el mismo archivo authorized_keys y llames a las cuentas separadas.

Para una operación de lanzamiento, una entrada de authorized_keys puede tener este aspecto:

restrict,command="/usr/local/libexec/release-service" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleOnlyReplaceThis release-broker

La opción restrict desactiva el reenvío de puertos, agente y X11, la asignación de TTY y la ejecución de ~/.ssh/rc. El manual de OpenSSH sshd(8) documenta restrict precisamente para este propósito y muestra su uso con un comando forzado.

El comando forzado no debe entregar la línea de comando original a sh -c. Debe ignorar SSH_ORIGINAL_COMMAND, salvo que dispongas de un analizador limitado y probado. El wrapper debe aceptar un protocolo fijo, validar cada campo, escribir una entrada de auditoría e invocar la operación real con límites explícitos para cada argumento.

Un wrapper pequeño de shell es aceptable si sigue siendo pequeño:

#!/bin/sh
set -eu

service=${1:-}
version=${2:-}

case "$service" in
  api|worker) ;;
  *) echo "unsupported service" >&2; exit 64 ;;
esac

case "$version" in
  *[!0-9A-Za-z._-]*|"") echo "invalid version" >&2; exit 64 ;;
esac

exec /usr/bin/sudo /usr/local/sbin/deploy-approved-release "$service" "$version"

Llama a ese wrapper con argumentos fijos desde el intermediario. No permitas que el cliente elija su ruta. Si necesitas más operaciones, crea más wrappers o un pequeño distribuidor de comandos que acepte subcomandos con nombre y rechace todo lo demás.

Aquí establezco un límite firme: no conectes un agente autónomo a una cuenta ops compartida con un shell normal y compenses la situación con un prompt mejor. Una cuenta de shell compartida convierte todas las protecciones del servidor en algo voluntario.

Para los trabajos con estado, usa operaciones idempotentes. Un wrapper de lanzamiento debe comprobar si el artefacto solicitado ya está activo, si el servicio funciona correctamente y si existe un punto de rollback antes de cambiar nada. El agente puede repetir una solicitud después de un tiempo de espera; tu operación remota no debe interpretar la repetición como permiso para realizar dos veces la acción.

La verificación del host y la gramática de los comandos merecen el mismo cuidado

Evita las reglas basadas en políticas
Usa el modelo fijo de decisión con tres controles en lugar de escribir reglas para cada solicitud del agente.

Una identidad privada protege la autenticación del cliente. No demuestra que el agente haya llegado al servidor previsto. Si tu automatización acepta cualquier huella de host nueva, un error de DNS, un archivo hosts manipulado o un atacante activo en la red pueden redirigir la conexión a un servidor que recibirá tu comando y conocerá su salida.

Usa StrictHostKeyChecking yes para las identidades de automatización. Distribuye las huellas de host revisadas mediante la gestión de configuración o conserva un archivo known_hosts cuidadosamente controlado. Cuando un host cambie su clave de host SSH, realiza un cambio explícito con una verificación fuera de banda. No enseñes al agente a responder «sí» al aviso de la clave del host.

Un perfil de cliente mínimo para una acción no interactiva suele tener este aspecto:

Host deploy-01.internal.example
    HostName deploy-01.internal.example
    User release
    IdentityAgent /path/to/broker.sock
    IdentitiesOnly yes
    StrictHostKeyChecking yes
    UserKnownHostsFile /Library/Application Support/agent-ssh/known_hosts
    BatchMode yes
    RequestTTY no
    ForwardAgent no

IdentitiesOnly yes impide que SSH envíe al destino todas las identidades disponibles mediante un agente. Reduce los intentos de autenticación innecesarios y evita el uso accidental de una identidad personal cuando falle la identidad de acción prevista. El manual de OpenSSH ssh_config(5) lo describe como una forma de usar las identidades configuradas en lugar de identidades adicionales ofrecidas por un agente o proveedor.

No hagas que el agente elija los nombres de host si puedes evitarlo. Una solicitud debería referirse a un objetivo lógico aprobado, como production-api-release, y el lado confiable debería asignar ese nombre a un hostname, una cuenta remota, una huella de host, una identidad y una familia de comandos. El mapa es una política en el sentido habitual, pero debe consistir en datos que una persona pueda inspeccionar, no en un lenguaje ingenioso que fomente los resquicios.

La gramática de los comandos necesita la misma moderación. Permitir argumentos arbitrarios para un binario fijo todavía puede equivaler a una ejecución arbitraria si el binario acepta rutas de archivos, nombres de plugins, importaciones de configuración o indicadores --exec. Inspecciona la CLI real. Escribe cuáles son los tokens permitidos. Prueba entradas malformadas, espacios, metacaracteres del shell, casos extraños de Unicode e indicadores repetidos.

Veinte minutos intentando abusar de tu propio wrapper con argumentos desagradables descubrirán más problemas que otro aviso de aprobación.

Aprueba la autoridad en el momento en que resulta útil

La aprobación humana debe situarse en el límite donde un proceso obtiene por primera vez una capacidad SSH, no después de cada comando inofensivo ni únicamente después de que un comando destructivo haya llegado al servidor.

La aprobación por sesión es un valor predeterminado práctico para una ejecución del agente. El primer intento de acción SSH de un proceso nuevo activa una decisión. La aprobación debe indicar qué proceso firmado la solicitó, qué identidad quiere utilizar y qué clase de acceso remoto recibirá. Si se aprueba, ese proceso exacto puede realizar solicitudes permitidas hasta que termine.

Así evitas convertir los diagnósticos rutinarios en una pila de clics. También evitas la alternativa peor: una aprobación que se aplique a todos los procesos futuros llamados node, python o claude de la máquina.

Algunas identidades merecen un segundo control en cada uso. Los despliegues en producción, los reinicios de emergencia, las exportaciones de bases de datos, las modificaciones de infraestructura y los comandos que pueden cambiar la accesibilidad de la red son buenos candidatos. El coste es la interrupción. El beneficio es que una sesión comprometida no puede utilizar silenciosamente la identidad más peligrosa después de que hayas aprobado una comprobación de estado de bajo riesgo.

Sallyport puede exigir una aprobación por llamada para una identidad SSH concreta, mientras que su autorización de sesión normal asocia la concesión a un proceso de agente determinado. Su control de bóveda también deniega las acciones mientras está bloqueada, en lugar de permitir que un agente en segundo plano siga funcionando después de que la persona se aleje.

El aviso de aprobación no debe pedir a los usuarios que lean un párrafo de JSON serializado. Muestra un resumen conciso de la acción y ofrece los detalles: destino, cuenta remota, nombre fijo del comando, argumentos proporcionados y tiempo de espera. Las personas pueden distinguir rápidamente production-db de staging-db. No pueden detectar de forma fiable el peligro en una tubería de shell completa después del décimo aviso.

Una denegación debe ser un resultado de primera clase. El agente necesita una respuesta explícita de rechazo para poder informar de que no tenía permiso, en lugar de reintentarlo con otra cuenta, otro host o una solución alternativa. Los intentos repetidos después de una denegación deben quedar registrados de forma visible.

El registro de auditoría debe sobrevivir al solicitante comprometido

Pon MCP detrás de una aprobación
El sp mcp incluido acepta llamadas MCP habituales mientras la app de Mac conserva la identidad SSH.

Los registros generados por el agente no bastan. Si el proceso del agente puede escribir o eliminar el registro de sus propias llamadas SSH, puede dejar una versión agradable de la historia.

Registra la actividad fuera del proceso del agente. Como mínimo, conserva la identidad del proceso solicitante, el identificador de sesión, la hora, el destino, la cuenta remota, el nombre de la acción, los argumentos después de aplicar las reglas de redacción, el resultado de la autorización, el código de salida, la duración y una captura limitada de stdout y stderr. Captura las primeras y las últimas 50 líneas de los comandos ruidosos, o guarda un hash del contenido junto con el artefacto completo protegido cuando la salida pueda contener secretos.

No registres claves privadas sin procesar, tokens portadores ni variables de entorno arbitrarias. Un sistema de auditoría que crea una segunda filtración de credenciales es peor que no tener sistema de auditoría, porque la gente confiará en él.

La evidencia de manipulación cambia la forma de investigar. Un registro encadenado puede revelar que alguien eliminó o reordenó registros después de los hechos, mientras que un archivo de texto normal de solo adición suele demostrar únicamente que existe un archivo. La verificación debe funcionar sin exigir que la bóveda esté desbloqueada; de lo contrario, no podrás examinar el registro cuando el sistema se encuentre precisamente en el estado en el que más necesitas evidencias.

La guía de evaluación de equipos rojos de CISA ofrece un motivo concreto para preocuparse por la contención de credenciales. Su evaluación publicada describe cómo un equipo obtuvo docenas de claves privadas SSH de archivos accesibles y utilizó identidades privilegiadas para moverse entre sistemas Linux. La lección no es que todos los agentes se conviertan en intrusos. La lección es que el material SSH reutilizable se acumula como un inventario de movimiento lateral cuando llega a lugares que no lo necesitan.

Cuando aparezca un comando inesperado, revoca primero la sesión del agente. Después, deshabilita la identidad afectada en el servidor, inspecciona el registro de actividad verificado y revisa los registros de sshd y del sistema del host de destino. Rota la identidad privada si existe alguna posibilidad de que haya salido del límite protegido. Un modelo mediado hace que esta secuencia sea más rápida porque revocar una sesión detiene las futuras solicitudes de acción sin tener que esperar a encontrar una clave privada copiada.

Usa cuatro rutas limitadas en lugar de un shell general

El despliegue práctico consiste en inventariar las acciones remotas que tus agentes ya intentan realizar y clasificarlas según sus consecuencias. No empieces preguntando qué claves privadas necesitan. Esa pregunta comienza por el extremo equivocado.

La mayoría de los equipos encuentra un conjunto pequeño de operaciones recurrentes:

  • Leer el estado limitado de un servicio o un fragmento reciente del registro.
  • Desplegar un artefacto ya creado en un entorno.
  • Ejecutar una comprobación de migración que no modifique datos.
  • Reiniciar un servicio concreto después de un lanzamiento.
  • Recopilar diagnósticos de un trabajo fallido.

Crea una ruta de acción para cada una. Asigna una cuenta o identidad remota dedicada cuando los servidores sean diferentes. Fuerza el comando en el servidor. Fija la identidad del host. Decide si la acción necesita aprobación de sesión o aprobación en cada uso. Registra tanto las llamadas permitidas como las rechazadas.

Mantén una ruta SSH humana para los trabajos de reparación inusuales. Durante un incidente, las personas a veces necesitan un shell interactivo, y fingir lo contrario las empuja hacia salidas inseguras. Esa ruta debe usar una identidad personal separada, MFA cuando esté disponible, un host de salto cuando corresponda y los controles habituales de incidentes. No debe compartir la identidad de automatización solo porque compartirla ahorra una línea en authorized_keys.

El patrón más seguro exige más ingeniería inicial: los wrappers necesitan pruebas, las huellas de host necesitan responsables y el catálogo de acciones necesita mantenimiento. Asume ese coste. La alternativa es conceder a un generador de texto probabilístico una credencial que puede sobrevivir a todas las barreras que hayas puesto alrededor de su tarea actual.

Empieza por la clave privada SSH más cercana a producción. Retírala del alcance del agente, sustituye un comando de shell amplio por una acción limitada e inspecciona el registro resultante después de una ejecución real. Ese primer límite te mostrará exactamente dónde se esconde el resto del trabajo.

FAQ

¿Puede un agente de IA usar SSH sin acceder a una clave privada?

Un agente puede ejecutar comandos SSH sin recibir una clave privada si un intermediario local independiente conserva la identidad y realiza el protocolo de conexión SSH. El agente envía el host, la cuenta, el comando y los argumentos; el intermediario decide si autoriza la solicitud y devuelve stdout, stderr y el código de salida. La diferencia es importante: una clave privada copiada puede reutilizarse en cualquier lugar, mientras que una acción mediada se puede detener, limitar y registrar.

¿Es seguro el reenvío del agente SSH para los agentes de IA?

El reenvío del agente SSH mantiene la clave privada fuera del host remoto, pero expone una capacidad de firma mediante un socket Unix reenviado. Un proceso que pueda acceder a ese socket puede autenticarse con las identidades cargadas en tu agente local. OpenSSH advierte que los usuarios capaces de eludir los permisos del host remoto pueden usar el agente reenviado para realizar operaciones de autenticación.

¿Debería un agente de IA tener su propia identidad SSH?

Usa una identidad SSH independiente para cada límite de automatización: los despliegues en producción, los diagnósticos de solo lectura, las copias de seguridad y el mantenimiento de repositorios no deberían compartir una cuenta general. Concede a cada identidad únicamente el acceso al servidor y el comando forzado que necesita. Una identidad de administrador general resulta cómoda, pero hace que cualquier error del agente sea mucho más costoso.

¿Cómo puedo restringir una identidad SSH a un solo comando?

Un comando forzado funciona cuando la tarea tiene una forma limitada, como desplegar un servicio, recopilar un informe de estado o rotar un artefacto controlado. Añade restrict,command="..." delante de la identidad pública en authorized_keys y valida los argumentos en el wrapper del servidor. No dependas de un comando forzado que pase un SSH_ORIGINAL_COMMAND sin comillas a un shell.

¿Debería un agente de IA conectarse alguna vez como root?

Por lo general, no. Crea una cuenta de servicio independiente en el host, prohíbe el inicio de sesión directo como root y concede solo los subcomandos de sudo que necesite el wrapper. Si una tarea realmente necesita privilegios de root, haz que ese privilegio sea visible en un programa pequeño del servidor en lugar de dar al agente un shell interactivo de root.

¿Cuándo deberían requerir aprobación humana las acciones SSH?

La aprobación por sesión es adecuada cuando un proceso de agente conocido necesita varias llamadas de bajo riesgo durante una ejecución limitada. La aprobación por llamada encaja con identidades capaces de desplegar, cambiar reglas del firewall, acceder a bases de datos de producción o ejecutar tareas de mantenimiento destructivas. La aprobación solo sirve si el aviso indica qué proceso firmado la solicita y qué cuenta y host utilizará.

¿Cómo debe verificar un agente las identidades de los hosts SSH?

Usa huellas de host fijadas o revisadas en known_hosts, establece StrictHostKeyChecking yes y haz que los hosts desconocidos fallen en lugar de añadirse automáticamente. No permitas que un agente acepte una huella modificada solo para terminar una tarea. Un cambio en la identidad del host es un incidente hasta que alguien demuestre lo contrario.

¿Qué debo registrar de los comandos SSH ejecutados por una IA?

Los registros útiles incluyen la identidad del proceso solicitante, el identificador de sesión, el host de destino, la cuenta remota, el comando y los argumentos exactos, la decisión de autorización, las horas de inicio y finalización, el estado de salida y la política aplicada a la salida capturada. Registra también las denegaciones. Un comando correcto sin la identidad de quien lo solicitó es una evidencia débil durante una investigación.

¿Qué debo hacer si entregué una clave privada SSH a un agente de IA?

Rota la identidad afectada, elimina su parte pública de todos los lugares autorizados, termina las sesiones activas y revisa el historial de comandos y los registros de los hosts de destino. Si la clave privada llegó a un prompt del modelo, un repositorio, una transcripción de chat o un artefacto de compilación, considera expuesta cada ruta por la que pudo copiarse. Después, rediseña el flujo para que el agente solicite acciones en lugar de recibir credenciales reutilizables.

¿Es adecuada una puerta de enlace SSH local para Mac para CI o automatización sin interfaz?

Un intermediario local para Mac funciona bien cuando los desarrolladores ejecutan agentes de programación en Mac administrados y necesitan que haya una persona presente para las acciones sensibles. No es adecuado para ejecutores de CI desatendidos, hosts de compilación Linux ni trabajos del servidor que no puedan usar un límite local de aprobación de escritorio. Esos casos necesitan otro límite de ejecución, como identidades de carga de trabajo de corta duración y un ejecutor controlado.

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