8 min de lectura

Archivos de inicio de SSH: por qué los comandos remotos engañan a los agentes

Los archivos de inicio de SSH pueden alterar los comandos de agentes remotos mediante perfiles, alias, funciones, cambios en PATH, comportamiento del TTY y reglas del servidor.

Archivos de inicio de SSH: por qué los comandos remotos engañan a los agentes

Un comando SSH no es automáticamente el programa que escribiste. Antes de que la máquina remota ejecute git, python o un script de despliegue, el demonio SSH selecciona una cuenta, inicia el shell de esa cuenta y le entrega una cadena de comandos. Los archivos de inicio y las reglas del servidor pueden cambiar el entorno, sustituir el comando o hacer que una ejecución sea interactiva mientras otra sigue siendo no interactiva.

Esto importa aún más cuando un agente informa del resultado. Una persona que ve un banner inesperado, un alias o un prompt en color puede detenerse e investigar. Un agente puede interpretar el código de salida 0 y una línea de salida conocida como prueba de que se ejecutó el programa previsto. He visto cómo esa suposición convertía una comprobación de estado inofensiva en una llamada a un script wrapper y una comprobación de despliegue en el resultado del ejecutable equivocado.

La solución no consiste en borrar todos los archivos de perfil. Las personas necesitan shells interactivos útiles. Hay que identificar la ruta de ejecución, separar la comodidad humana de la automatización y hacer explícito el contrato del comando remoto.

Un comando remoto pasa primero por el shell de la cuenta

OpenSSH normalmente no ejecuta las palabras que siguen a ssh host mediante un execve directo del binario de destino. El manual de sshd indica que, después de la autenticación, sshd ejecuta el comando solicitado a través del shell del usuario, usando la opción -c del shell. La ruta del shell de inicio de sesión procede de la base de datos de cuentas, no de la máquina local que abrió la conexión SSH.

Ese detalle explica muchos informes confusos. Supón que un agente envía:

ssh deploy@buildbox git -C /srv/app rev-parse HEAD

La cuenta remota podría usar Bash, zsh, fish, un shell restringido o un wrapper del sitio. El shell seleccionado recibe un comando equivalente a git -C /srv/app rev-parse HEAD. Puede inicializarse primero. También puede recibir un comando sustituido por sshd antes de llegar a ese punto.

Esto es independiente del shell que el agente usó localmente. Un agente puede ejecutarse desde un proceso limpio en un Mac mientras la cuenta remota deploy conserva diez años de personalizaciones del shell. Un prompt local limpio no vuelve limpio el extremo remoto.

Tampoco confundas el análisis de comandos del shell con el transporte SSH. SSH cifra la conexión y autentica la cuenta. No garantiza que python sea el binario que esperabas, que PATH no haya cambiado ni que un perfil no haya escrito texto en la salida estándar.

Por eso, la primera pregunta práctica no es «¿SSH se conectó?». Es «¿Qué programa interpretó el comando remoto, con qué cuenta y bajo qué reglas de inicialización?»

El modo del shell decide qué archivos intervienen

El comportamiento de inicio del shell depende de la familia del shell y del modo de invocación. Las etiquetas que se usan informalmente, «un shell SSH» o «un shell Bash», no son lo bastante precisas para predecir el comportamiento.

En Bash, el Manual de referencia de GNU Bash distingue entre la invocación de inicio de sesión, interactiva y no interactiva. Un shell Bash de inicio de sesión lee /etc/profile y después el primer archivo personal legible entre ~/.bash_profile, ~/.bash_login y ~/.profile. Un shell interactivo que no es de inicio de sesión lee ~/.bashrc.

Un comando remoto normal suele ejecutarse en un shell no interactivo. Eso no significa que no cargue nada. Bash lee el archivo indicado por BASH_ENV, si esa variable de entorno está definida, antes de ejecutar un comando no interactivo. El manual de Bash también documenta un tratamiento especial cuando Bash detecta que sshd lo inició con la entrada estándar conectada a una conexión de red: puede leer ~/.bashrc. No bases la automatización en la regla popular de que .bashrc solo afecta al uso interactivo.

zsh tiene otro mapa. /etc/zshenv y ~/.zshenv se aplican a todas las invocaciones de zsh, lo que vuelve especialmente peligroso un .zshenv ruidoso o con efectos persistentes. zsh lee .zprofile para los shells de inicio de sesión y .zshrc para los shells interactivos. Quien coloca cambios de PATH y mensajes de estado en .zshenv también ha cambiado los comandos remotos, los scripts y, a menudo, el inicio de aplicaciones gráficas.

POSIX sh no ofrece una vía de escape universal. Las implementaciones varían. La especificación del shell POSIX describe el archivo ENV para los shells interactivos, pero el /bin/sh de un sistema puede ser dash, Bash en modo de compatibilidad u otra implementación con sus propios detalles. Prueba el host real en lugar de asumir que un nombre de archivo significa lo mismo en todas partes.

La distinción tiene una consecuencia operativa clara. Un comando que funciona en una sesión interactiva de diagnóstico puede fallar para un agente porque la sesión interactiva lee un perfil que la sesión del comando omite. También ocurre lo contrario: un hook de automatización puede afectar a las sesiones de comandos mientras la terminal de una persona no lo nota.

Mantén los ajustes interactivos en archivos que solo lean los shells interactivos. Los prompts, la configuración del autocompletado, los títulos de terminal, los valores predeterminados de color y los saludos deben ir allí. Coloca los requisitos de entorno de la automatización en un archivo pequeño y documentado que un lanzador controlado cargue de forma deliberada. No permitas que un agente descubra su entorno de ejecución heredando los dotfiles de un desarrollador.

Los cambios en PATH alteran la identidad, no solo la comodidad

PATH suele tratarse como un ajuste de comodidad. En una ejecución desatendida, selecciona la identidad del programa. Si un perfil antepone /opt/team/bin, entonces curl, git, ssh o python pueden referirse a un wrapper en lugar del programa del sistema.

Ese wrapper puede ser intencionado. Los equipos usan wrappers para elegir credenciales de nube, imponer comprobaciones de repositorios, añadir telemetría o seleccionar entornos de ejecución de lenguajes. El error consiste en permitir que un agente suponga que un comando sin calificar significa el ejecutable del proveedor. Solo significa «el primer ejecutable coincidente en el PATH que este shell tiene en ese momento».

Los alias y las funciones crean una ambigüedad parecida, aunque su comportamiento depende del modo del shell. Bash normalmente no expande alias en un shell no interactivo, a menos que expand_aliases esté activado. Por eso los alias son menos comunes en las ejecuciones estándar de comandos SSH, pero no imposibles. Un archivo cargado puede activar la expansión. Las funciones no necesitan expansión de alias. Un perfil puede definir una función llamada git, exportar el estado del entorno y hacer que todos los comandos posteriores de ese shell llamen a la función.

Empieza preguntando al shell, pero considera su respuesta una prueba del entorno que estás inspeccionando, no una demostración universal:

ssh -T deploy@buildbox '\nprintf "shell argv0: %s\\n" "$0"\nprintf "shell flags: %s\\n" "$-"\nprintf "PATH: %s\\n" "$PATH"\ncommand -V git\ncommand -V python\ncommand -V curl\n'

Un resultado habitual podría ser este:

shell argv0: -bash
shell flags: hBc
PATH: /opt/team/bin:/usr/local/bin:/usr/bin:/bin
git is /opt/team/bin/git
python is /usr/local/bin/python
curl is /usr/bin/curl

El builtin command -V puede informar de un alias, una función, un builtin o una ruta. En los shells que lo admiten, type -a git puede mostrar más de una ruta coincidente. En Bash, declare -f git imprime el cuerpo de una función si git es el nombre de una función. Estas comprobaciones dejan al descubierto un fallo común: un perfil define una función git() que ejecuta un comando Git real y después envía discretamente un evento de estado. La salida sigue pareciendo salida de Git. El efecto secundario ocurre en otro lugar.

La caché de comandos añade otra complicación. Algunos shells guardan dónde encontraron un comando. Si un perfil cambia PATH después de que el shell haya resuelto un nombre, el shell puede seguir usando la ubicación almacenada hasta que hash -r o su equivalente borre la caché. Esto aparece sobre todo en shells interactivos de larga duración, pero los agentes que mantienen vivo un proceso de shell también pueden encontrárselo.

Usa rutas absolutas para los comandos cuya identidad afecte a una decisión de seguridad o a un resultado de despliegue. No escribas /usr/bin/git solo porque exista en tu portátil. Verifica la ruta esperada en el sistema operativo de destino, regístrala y pruébala con la cuenta que ejecutará el trabajo. Si el despliegue utiliza deliberadamente un gestor de versiones o un wrapper, nombra ese wrapper de forma explícita y convierte su contrato en parte del trabajo.

Un pseudo-terminal cambia más que el formato

ssh host command normalmente no asigna un pseudo-terminal. ssh -t host command lo fuerza. Esa sola opción puede cambiar las ramas de inicio del shell, afectar al buffering, hacer que los programas emitan códigos de color y provocar solicitudes de entrada que una ejecución sin TTY nunca haría.

Muchos archivos de configuración del shell empiezan con una comprobación como esta:

case $- in
  *i*) ;;
  *) return ;;
esac

Esa comprobación sale del resto del archivo a menos que el shell se identifique como interactivo. Un pseudo-terminal puede hacer que un shell sea interactivo en circunstancias en las que una conexión de comandos normal no lo sería. El comando recibe entonces alias, configuración del autocompletado, helpers del prompt, cambios de PATH y exportaciones específicas del terminal que no estaban presentes en la ejecución del agente.

Los programas también reaccionan directamente al terminal. Un comando puede mostrar una barra de progreso, paginar la salida, elegir otro formato de diagnóstico o leer una confirmación. Un parser de máquina que espera un único objeto JSON puede fallar porque un perfil imprime un saludo antes de que se inicie el programa o porque el programa detecta un TTY y emite caracteres de control.

Prueba ambos modos cuando investigues una discrepancia:

ssh -T deploy@buildbox 'printf "flags=%s tty=" "$-"; test -t 1 \u0026\u0026 echo yes || echo no'
ssh -tt deploy@buildbox 'printf "flags=%s tty=" "$-"; test -t 1 \u0026\u0026 echo yes || echo no'

El primer comando pide a SSH que no asigne un terminal. El segundo fuerza uno incluso cuando la entrada estándar local no es un terminal. Compara la salida y después compara la resolución de comandos y PATH en cada modo. Si los resultados difieren, no corrijas primero el parser. Encuentra la rama de inicio que produjo la diferencia.

La automatización debería usar -T de forma predeterminada. Asigna un terminal solo a los comandos que realmente lo necesiten, como una tarea controlada de recuperación interactiva. Si un agente necesita un terminal para ejecutar una consulta de estado rutinaria, ya está trabajando en un entorno menos predecible.

Las reglas del servidor pueden sustituir el comando solicitado

Mantén las claves SSH fuera de los agentes
Sallyport ejecuta SSH mediante sp-ssh, así que el agente nunca recibe la clave SSH.

Los archivos de inicio son solo una capa. El servidor puede sustituir o restringir un comando antes de que el shell de la cuenta lo vea. Si inspeccionas .bashrc y te detienes ahí, puedes pasar por alto la regla que realmente cambió el resultado.

El manual de sshd_config documenta ForceCommand. Un administrador puede aplicarlo globalmente o dentro de un bloque Match para un usuario, grupo, dirección u otra condición. Con ForceCommand internal-sftp, por ejemplo, el servidor ignora los comandos de shell normales y ejecuta el servicio SFTP interno. Con un wrapper personalizado, el wrapper recibe el contexto del comando solicitado y decide qué hacer.

Una entrada de clave pública SSH también puede incluir una restricción command="..." en el archivo authorized_keys de la cuenta. Esto es habitual en cuentas de copias de seguridad, acceso a repositorios, transferencia de archivos y automatización con un alcance limitado. Puede ser una buena práctica de seguridad. Se convierte en un problema de depuración cuando alguien entrega a un agente una credencial restringida y espera que ejecute comandos arbitrarios.

Los controles del entorno también forman parte de la revisión. AcceptEnv indica a sshd qué variables proporcionadas por el cliente acepta. SetEnv puede establecer variables en el servidor. PermitUserEnvironment, cuando está activado, puede permitir que el archivo de entorno SSH de una cuenta o las opciones de una clave autorizada establezcan valores. Estos ajustes pueden influir en PATH, la configuración regional, el comportamiento del runtime de un lenguaje y hooks como BASH_ENV.

Usa ssh -G en el cliente, pero conoce sus límites:

ssh -G buildbox | grep -E '^(hostname|user|port|requesttty|remotecommand|sendenv|setenv) '

OpenSSH muestra la configuración del cliente después de aplicar los bloques Host y los valores predeterminados locales. La salida puede revelar un RemoteCommand inesperado, una configuración forzada del terminal, una regla de reenvío de entorno o un host de destino diferente. No puede revelar ForceCommand del servidor, el shell de inicio de sesión de la cuenta remota ni las restricciones guardadas en authorized_keys.

Pide al propietario del servidor la configuración relevante de sshd_config y las restricciones de la cuenta cuando esta esté destinada a la automatización. Si no administras el host, solicita una interfaz de ejecución documentada en lugar de intentar reconstruir el comportamiento de un shell personal mediante pruebas sucesivas. Una cuenta con un wrapper forzado y opaco no es un endpoint SSH general, aunque acepte la autenticación.

Inspecciona la ruta de ejecución sin confiar en una sola prueba

Un comando de diagnóstico se ejecuta dentro del mismo entorno que está bajo sospecha. Eso no hace imposible el diagnóstico. Significa que debes recopilar varios datos independientes y especificar qué demuestra cada uno.

Primero, inspecciona la configuración del cliente local con ssh -G. Después determina el shell configurado para la cuenta remota mediante la base de datos de cuentas del host. En muchos hosts Linux, getent passwd deploy devuelve un registro separado por dos puntos cuyo último campo es la ruta del shell. En macOS, un administrador puede inspeccionar la cuenta con las herramientas de Directory Service. Cuando sea posible, hazlo desde un canal administrativo de confianza y no a través del shell potencialmente personalizado de la cuenta.

A continuación, obtén y revisa los archivos de inicio del shell real: archivos globales, archivos personales y todos los archivos que estos carguen. Busca estos tipos de comportamiento:

  • asignaciones de PATH=, inicialización de gestores de versiones y comandos hash
  • alias, definiciones de funciones y opciones del shell como expand_aliases
  • comandos que escriban en la salida, como echo, printf y helpers de control del terminal
  • BASH_ENV, ENV, variables de configuración regional y hooks de entorno específicos de lenguajes
  • ramas condicionales que comprueben -t, $-, $SSH_TTY o $TERM

No busques únicamente la palabra alias. Una línea como . ~/.local/share/tool/init.sh puede cargar el archivo que define la función que te interesa. Sigue la cadena de archivos cargados hasta el final. Los archivos de perfil suelen crecer hasta convertirse en una acumulación de inclusiones condicionales, y ahí es donde el comportamiento de la automatización deja de poder revisarse con claridad.

Después realiza una ejecución de huella limitada con un comando inofensivo. Registra los indicadores del shell, el directorio actual, PATH, los nombres de entorno relevantes y la resolución exacta de las herramientas que utilizará el trabajo. Evita volcar todas las variables de entorno en los registros. Los tokens y las credenciales de nube suelen vivir allí. Una transcripción de diagnóstico debe demostrar las condiciones de ejecución sin convertirse en un nuevo almacén de secretos.

Por último, prueba el comando exacto de producción en el modo exacto que usará el agente: la misma cuenta, sin terminal salvo que sea necesario, el mismo transporte de entrada y el mismo directorio de trabajo. Un resultado obtenido mediante el inicio de sesión interactivo de un administrador no lo sustituye. Responde a otra pregunta.

Conserva las pruebas junto con la definición del despliegue o de la automatización. El recurso útil no es una captura de pantalla de una terminal funcionando. Es un documento breve que indique el shell de la cuenta, los archivos de inicio que pueden afectar a la ejecución, las rutas de los ejecutables necesarios, el entorno esperado, la política de terminales y las restricciones de comandos del servidor.

Haz que el shell de automatización sea deliberadamente aburrido

Pon SSH detrás de una puerta de enlace
Usa el MCP shim incluido para enviar las acciones SSH del agente a través de Sallyport en lugar de su proceso.

Una acción remota fiable debería entrar en un shell conocido con un entorno reducido y ejecutar después binarios identificados. Esto no elimina el shell inicial de la cuenta que usa sshd, pero limita cuánto estado heredado llega al programa que realiza el trabajo.

Para un script pequeño y fijo, envía el script por la entrada estándar y ejecuta un shell conocido con un entorno vacío. La cadena de comandos remota permanece fija, lo que también evita construir una frágil torre de escapes de comillas locales y remotas.

ssh -T deploy@buildbox '/usr/bin/env -i PATH=/usr/bin:/bin /bin/sh -s' \u003c\u003c'REMOTE'
set -eu
PATH=/usr/bin:/bin
export PATH

/usr/bin/git -C /srv/app rev-parse HEAD
REMOTE

Esto ofrece varias ventajas. -T evita un terminal. /usr/bin/env -i borra las variables heredadas. /bin/sh -s lee el script literal desde la entrada estándar y el heredoc entre comillas impide que el shell local expanda $PATH u otro texto antes de transmitirlo. set -eu detiene la ejecución ante un parámetro no definido o un comando simple fallido, sujeto a la semántica normal del shell.

También tiene límites. /usr/bin/env, /bin/sh y /usr/bin/git son ejemplos, no rutas que debas copiar a ciegas en todos los hosts. Confirma las rutas en cada clase de destino. Limpiar el entorno puede eliminar variables que un programa necesita legítimamente, como el directorio personal, la configuración regional, la configuración del proxy o la ubicación del runtime. Añade únicamente las variables identificadas que el programa necesite y documenta por qué existe cada una.

No uses env -i para ocultar una configuración defectuosa de la cuenta. Si un archivo de inicio modifica el shell inicial de forma tan agresiva que impide ejecutar el lanzador fijo, la cuenta no es adecuada para trabajos desatendidos. Usa una cuenta específica con un shell de inicio controlado y archivos de inicio mínimos.

Evita introducir texto arbitrario del agente en una cadena remota sh -c. Los errores de comillas pueden convertir los datos en sintaxis del shell antes de que el script previsto los reciba. Pasa los datos por un canal restringido, usa un script remoto fijo con argumentos validados o emplea un protocolo diseñado para solicitudes estructuradas. El shell es potente porque analiza el texto como código. Un agente no debería difuminar accidentalmente ese límite.

Separa las cuentas interactivas de las cuentas de agentes

Conserva pruebas SSH resistentes a manipulaciones
Sallyport conserva un único registro de auditoría cifrado y encadenado mediante hashes para el historial de sesiones y llamadas.

El diseño más limpio asigna identidades remotas distintas a las personas y a la automatización. Una cuenta de desarrollador puede conservar su prompt, autocompletado, gestores de lenguajes y helpers personales. Una cuenta de automatización debería tener un shell declarado, un directorio personal pequeño y archivos de inicio que no hagan nada en las sesiones de comandos o ejecuten una configuración revisada de forma estricta.

Esta separación no es burocracia. Permite responder preguntas sencillas pero necesarias: ¿Qué binario de Git hace el despliegue? ¿Cuál es el directorio inicial? ¿La cuenta acepta un terminal? ¿Qué nombres de entorno pueden afectar a una versión? ¿Quién puede cambiar el wrapper que ejecuta los comandos?

Una cuenta específica también facilita razonar sobre las restricciones de comandos. Puedes usar un wrapper forzado para las pocas acciones que esa cuenta debe realizar y rechazar todo lo demás. Eso no convierte el wrapper en un lenguaje de políticas. Mantenlo lo bastante sencillo para inspeccionarlo: valida los argumentos, establece el entorno documentado, invoca una ruta absoluta del programa y escribe un registro de auditoría.

No resuelvas esto colocando un gran case con docenas de excepciones en .bashrc. Este enfoque es popular porque cada usuario ya tiene un archivo de perfil y no hace falta cambiar el despliegue. Falla porque la semántica del perfil varía según el modo del shell, el orden de carga se vuelve oscuro y una edición interactiva inofensiva puede alterar el comportamiento desatendido. Coloca la configuración de automatización en el lanzador o en el script específico que sea responsable del contrato de automatización.

Sallyport puede mantener las credenciales SSH fuera del proceso del agente y ejecutar acciones SSH mediante su helper sp-ssh incluido, pero no puede hacer determinista una cuenta remota sin control. Trata la revisión de la cuenta remota como parte del diseño de la acción y usa después el registro de actividad para comparar lo que solicitó el agente con lo que devolvió el extremo remoto.

Confía en los resultados solo después de fijar el contrato

El resultado de un comando de agente es fiable cuando puedes afirmar qué se ejecutó sin depender de los hábitos actuales del shell de una persona. Esa afirmación necesita más que un hostname y un código de salida. Debe identificar la cuenta SSH, la identidad del host de destino, la configuración del terminal, la restricción de comandos del servidor si existe, el shell seleccionado, la construcción del entorno, el origen del script y la ruta del ejecutable.

Aquí existe un límite incómodo. No puedes demostrar mediante la propia salida de un comando remoto que el shell remoto no modificó el comando antes de imprimirla. Si el shell de la cuenta, la restricción de la clave autorizada o el comando forzado están fuera de tu control, necesitas pruebas administrativas o una cuenta diferente. Repetir la misma prueba diez veces solo repite la misma suposición.

Empieza por los comandos que los agentes ya ejecutan y que pueden cambiar código, infraestructura o datos de producción. Para cada uno, ejecútalo con y sin terminal, comprueba cómo se resuelve su ejecutable y sustituye la configuración heredada por un lanzador explícito cuando ese resultado importe. La primera sorpresa suele ser PATH. La segunda suele ser un archivo de inicio que alguien olvidó que todavía se estaba cargando.

Cuando encuentres una de esas sorpresas, no añadas otra condición a un perfil y lo des por solucionado. Mueve el comportamiento a una cuenta controlada o a un script fijo, registra el contrato del comando y haz que la siguiente ejecución del agente sea lo bastante aburrida como para que su salida signifique exactamente lo que dice.

FAQ

¿ssh host command carga los archivos de inicio del shell?

No. SSH inicia un proceso mediante el shell configurado para la cuenta, y ese shell puede leer archivos de inicio antes de ejecutar el comando. Un comando sencillo puede heredar un PATH modificado, variables exportadas, funciones o un wrapper forzado.

¿.bashrc se ejecuta cuando SSH ejecuta un comando remoto?

Por lo general, no en un comando Bash normal y no interactivo, pero esa palabra, «por lo general», es la razón por la que los agentes tienen problemas. Bash puede leer BASH_ENV y tiene un comportamiento especial cuando sshd lo inicia con la entrada estándar conectada a una red. Otros shells tienen sus propias reglas.

¿Cómo ejecuto un comando remoto limpio mediante SSH?

Usa ssh -T para evitar un pseudo-terminal, invoca un shell conocido mediante su ruta absoluta, limpia el entorno con env -i y usa rutas absolutas para los programas importantes. Esto reduce las variaciones accidentales, pero no puede contrarrestar una cuenta SSH sujeta a ForceCommand ni un shell controlado por otra persona.

¿Por qué ssh -t cambia la salida de mi comando?

Un pseudo-terminal puede hacer que el shell se clasifique como interactivo, lo que suele provocar que cargue un conjunto distinto de archivos. También puede cambiar el formato de salida, los avisos, el uso del color, los saltos de línea y el comportamiento de las herramientas que detectan si la salida estándar es un terminal.

¿Cómo puedo saber si un comando remoto es un alias o una función?

command -V tool muestra cómo resolvería el shell actual un nombre, incluidos alias, funciones, builtins y rutas. type -a tool resulta útil en los shells que lo admiten porque puede revelar varios ejecutables encontrados en PATH.

¿Los agentes de IA deberían usar una cuenta SSH compartida?

Usa una cuenta de automatización específica, con un shell documentado, un directorio personal mínimo y sin lógica de perfiles personales. No compartas la cuenta interactiva de un ingeniero con un agente no supervisado y luego trates su salida como prueba del despliegue.

¿Cuál es la diferencia entre los shells de inicio de sesión, interactivos y no interactivos?

Un shell de inicio de sesión lee archivos de inicio de sesión, como /etc/profile y uno de los perfiles personales de inicio de sesión de Bash. Un shell no interactivo ejecuta una cadena de comandos y puede leer un hook diferente, como BASH_ENV. Un shell interactivo activa comodidades para el usuario, como avisos y, a menudo, alias.

¿ssh -G puede mostrar lo que ocurre en el servidor remoto?

ssh -G host muestra la configuración del cliente después de que OpenSSH aplica los bloques Host y los valores predeterminados locales. No revela los archivos de inicio del servidor, el shell de la cuenta remota, ForceCommand ni una restricción de comandos en una entrada de authorized_keys.

¿Qué debo auditar antes de confiar en el resultado SSH de un agente?

Inspecciona el shell de la cuenta, los archivos de inicio, PATH, la resolución de comandos, las reglas del demonio SSH y las restricciones específicas de authorized_keys. Prueba el comando exacto con y sin TTY, y registra el contrato de ejecución resultante en lugar de confiar en el resultado de una terminal aislada.

¿Una puerta de enlace SSH puede impedir que los archivos de perfil cambien los comandos?

No. Una puerta de enlace puede mantener las credenciales SSH fuera del agente y registrar la acción, pero el host remoto sigue decidiendo qué shell de cuenta y qué reglas del servidor procesan la solicitud. Trata el control de credenciales y la determinación de la ejecución remota como tareas separadas.

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