# ¿Puede la transferencia de entorno SSH filtrar contexto local?

La transferencia de entorno SSH puede filtrar mucho más contexto local del que necesita una tarea remota. El canal está cifrado, pero el cifrado solo protege el trayecto. No convierte `AWS_PROFILE`, `GIT_AUTHOR_EMAIL`, el nombre de un inquilino ni una opción interna en entradas apropiadas para un proceso de otra máquina.

Trato cada variable transferida como un argumento de la orden remota. Por tanto, necesita un nombre, un motivo, un responsable y una prueba. Un comodín copiado de una configuración SSH cómoda para un portátil no cumple ese criterio, porque su significado cambia cada vez que alguien añade una variable local coincidente.

El objetivo seguro no es un entorno remoto vacío. `sshd`, la cuenta de acceso, el intérprete y los envoltorios crean su propia base. El objetivo es más preciso: el cliente aporta exactamente las variables de trabajo recogidas en un contrato escrito, el servidor no acepta un conjunto más amplio y una prueba comprueba tanto los valores necesarios como los señuelos rechazados.

## La transferencia solo ocurre si ambos extremos SSH están de acuerdo

La transferencia de entorno de OpenSSH tiene dos barreras. En el cliente, `SendEnv` selecciona nombres del entorno del proceso local, mientras que `SetEnv` del cliente proporciona pares literales `NOMBRE=VALOR`. En el servidor, `AcceptEnv` decide qué nombres enviados por el cliente entran en el entorno de la sesión. Por regla general, un nombre solo cruza cuando el cliente lo ofrece y el servidor lo acepta.

RFC 4254 describe el mecanismo que hay debajo de esos ajustes. Antes de iniciar el intérprete o la orden, el cliente puede enviar una petición de canal SSH de tipo `env` que contiene un nombre de variable y un valor. El RFC también advierte que configurar el entorno sin control puede ser peligroso en un proceso privilegiado y recomienda usar una lista permitida o esperar a que se hayan reducido los privilegios. Esa advertencia forma parte de la especificación del protocolo.

Los manuales de OpenSSH añaden una excepción que suele confundir las auditorías: cuando el cliente solicita un pseudoterminal, `TERM` siempre se envía y se acepta porque el protocolo la necesita. Ejecuta la automatización con `ssh -T` cuando no necesite terminal. Así eliminas de este camino el comportamiento del terminal, las sorpresas del inicio interactivo y `TERM`.

De este acuerdo se desprenden cuatro observaciones.

- Un `SendEnv` amplio permanece inactivo contra un servidor que no acepta nada, pero entra en vigor en cuanto un administrador amplía `AcceptEnv`.
- Un `AcceptEnv` amplio permanece inactivo para un cliente cuidadoso, pero cualquier usuario autorizado puede conectarse con otra configuración y proporcionar un valor coincidente.
- Ningún extremo puede imponer por sí solo todo el contrato cuando hay personas que controlan ambas configuraciones.
- Que una orden termine bien no dice qué peticiones de entorno rechazó el servidor.

El último punto importa. OpenSSH puede ignorar una variable ofrecida y continuar la sesión. Si un despliegue funciona porque el intérprete remoto ya define el mismo nombre, una prueba que solo comprueba el valor final puede atribuir a la transferencia un valor que nunca se entregó.

## Los comodines convierten el estado local futuro en entrada remota

`SendEnv WORKFLOW_*` no significa «las variables que revisé hoy». Significa todos los nombres coincidentes presentes en el entorno de cada proceso SSH futuro. Seis semanas después, alguien puede añadir `WORKFLOW_DEBUG_DUMP`, `WORKFLOW_CUSTOMER` o `WORKFLOW_TOKEN_FILE` a su perfil. La antigua regla SSH adquiere comportamiento nuevo sin avisar.

La transferencia de configuración regional muestra cómo se propaga. Muchas configuraciones de estación de trabajo envían `LANG` y `LC_*` para que una sesión interactiva muestre bien el texto. Puede ser razonable para un acceso humano, pero no pertenece automáticamente a una cuenta de compilación o despliegue no interactiva. Esos valores pueden cambiar la ordenación, las clases de caracteres, las fechas y los diagnósticos. Una tarea que analice la salida puede fallar sin que se filtre secreto alguno.

Los patrones con más riesgo son los que parecen espacios de nombres prácticos:

- `AWS_*` puede incluir perfiles, regiones, datos relacionados con credenciales y rutas de configuración.
- `GIT_*` puede transportar identidad, trazas, directorios de objetos alternativos o el comportamiento de askpass.
- `CI_*` suele mezclar etiquetas de compilación inocuas con contexto del proveedor y rutas temporales.
- `LC_*` parece cosmético hasta que un script depende de una intercalación o unos mensajes estables.
- `APP_*` suele crecer con la aplicación y rara vez tiene un único significado de seguridad.

No clasifiques un espacio de nombres como seguro. Clasifica nombres concretos. Puede que `DEPLOY_REGION` sea necesaria y `AWS_PROFILE` sea contexto de la estación. Puede que `BUILD_REF` sea necesaria mientras `GIT_CONFIG_COUNT` cambia la configuración de Git en ejecución. El prefijo común organiza, pero no crea una frontera de confianza.

Los valores también revelan contexto sin ser credenciales. Una ruta muestra un nombre de usuario y la estructura del repositorio. Un perfil identifica una cuenta o un entorno. Una opción de trazas puede hacer que una herramienta remota imprima datos de órdenes en un registro compartido. Después, un agente puede usar ese contexto en otras acciones aunque la primera orden solo lo mostrara. La filtración incluye influencia y divulgación no deseadas, no solo cadenas secretas.

## Una excepción que parece segura puede ampliarse meses después

La deriva de configuración suele crear esta filtración sin un único cambio temerario. Primero, alguien añade `SendEnv APP_*` a un bloque porque una prueba necesita `APP_COLOR=0`. El servidor lo rechaza y no ocurre nada. Más tarde, un administrador añade `AcceptEnv APP_*` para otro equipo que necesita dos ajustes en el mismo servidor compartido. Ambos cambios superan su revisión local porque cada revisor solo ve la mitad del acuerdo.

La siguiente conexión une las dos reglas inactivas. El intérprete local ya contiene `APP_CUSTOMER=acme-lab`, `APP_TRACE=1` y `APP_CONFIG=/Users/lee/work/private/config`. El cliente SSH ofrece las cuatro variables y el demonio las acepta. Un envoltorio de diagnóstico ejecuta `env` cuando falla la publicación y guarda la salida en un registro legible por el grupo. No se copió ningún token, pero identidad local, contexto del cliente, una ruta y una opción de trazas cruzaron la frontera sin aprobación.

Quitar el comodín del servidor corrige las sesiones futuras, pero no borra el registro ni indica qué órdenes vieron los valores. Trata el hallazgo como un incidente pequeño:

1. Deja de aceptar el patrón amplio y valida la configuración del demonio.
2. Identifica cuentas, clientes y periodo en que coincidieron ambos patrones.
3. Busca en los registros remotos aprobados los nombres expuestos, no sus valores sensibles.
4. Decide si cada valor cambió la conducta de la orden o reveló contexto a otro usuario.
5. Sustituye el comodín por nombres exactos y añade señuelos para las clases rechazadas.

Por eso «el servidor lo rechaza ahora» no defiende una regla amplia del cliente. La configuración inactiva no tiene responsable cuando se activa. Elimina las ofertas innecesarias del cliente aunque el servidor sea estricto, y elimina la aceptación innecesaria del servidor aunque los clientes actuales sean prudentes.

También ocurre la deriva inversa. Un servidor lleva años aceptando `LC_*` para usuarios interactivos. Una actualización de la imagen de automatización instala una configuración de cliente que envía `LC_*`. La tarea de despliegue hereda `LC_COLLATE` elegido por un desarrollador y genera otro orden de archivos. No hay una divulgación que escalar, pero el mismo acuerdo causó un fallo de integridad. Revisa juntos confidencialidad y comportamiento.

## Inspecciona la configuración que SSH usará de verdad

Lee la configuración evaluada del cliente antes de editar un archivo. `ssh -G` de OpenSSH aplica bloques `Host` y `Match`, inclusiones y configuraciones de usuario y sistema, y después imprime el resultado para el destino indicado. El archivo que parece autoritativo puede perder frente a un valor anterior o ganar entradas de una inclusión.

Ejecuta esto desde la misma cuenta y contexto que el flujo de trabajo:

```sh
ssh -G deploy-prod |
  awk '$1 == "sendenv" || $1 == "setenv" { print }'
```

Un resultado inseguro representativo tiene este aspecto:

```text
sendenv LANG
sendenv LC_*
sendenv AWS_*
setenv WORKFLOW_KIND=deploy
```

`ssh -G` no imprime los valores actuales seleccionados por `SendEnv`, sino las reglas efectivas. Eso es mejor para una revisión porque la salida no vuelca credenciales. También significa que la revisión queda incompleta hasta comparar los nombres o patrones con el entorno del proceso que inicia SSH.

Captura los nombres sin sus valores:

```sh
env | sed 's/=.*//' | LC_ALL=C sort > local-env.names
grep -E '^(LANG|LC_|AWS_|WORKFLOW_)' local-env.names
```

La expresión regular es una ayuda de inspección, no una política reutilizable. Adáptala a todos los patrones de `ssh -G`. Si un supervisor, IDE, agente o tarea programada inicia SSH, inspecciona el entorno de ese proceso y no tu intérprete interactivo. La herencia sigue el árbol de procesos; probar desde el padre equivocado ofrece una respuesta limpia pero irrelevante.

Revisa el servidor por separado. En OpenSSH, `sshd -T` comprueba e imprime los ajustes efectivos. Proporciona criterios de conexión cuando haya bloques `Match`:

```sh
sudo sshd -T \
  -C user=deploybot,host=deploy.example,addr=192.0.2.44 |
  grep '^acceptenv'
```

Usa el usuario, host y dirección reales de la conexión revisada. Conserva la dirección de documentación del ejemplo solo en ejemplos. Ejecuta también `sudo sshd -t` antes de recargar el demonio; validar la sintaxis cuesta poco y endurecer el entorno no justifica romper el acceso.

## Un archivo de cliente dedicado hace legible la lista permitida

Para automatización, la configuración más fiable es un archivo SSH pequeño pasado con `-F`. El manual indica que el archivo explícito sustituye el archivo normal del usuario y hace que se ignore el archivo general del sistema. Así una actualización del puesto o de la flota no puede añadir comodines regionales al flujo.

```sshconfig
Host deploy-prod
    HostName deploy.example
    User deploybot
    IdentityFile ~/.ssh/deploy_ed25519
    IdentitiesOnly yes
    RequestTTY no
    SendEnv DEPLOY_REGION
    SendEnv BUILD_REF
    SetEnv WORKFLOW_KIND=deploy
```

Invócalo de forma explícita:

```sh
ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release
```

`SendEnv` lee el valor del entorno del proceso `ssh` local. Úsalo cuando el valor cambie legítimamente en cada ejecución. `SetEnv` del cliente fija un literal en la configuración. Resérvalo para una etiqueta constante no secreta, no para una credencial ni para un valor que alguien olvidará actualizar.

OpenSSH permite además que un patrón `SendEnv` con prefijo `-` borre nombres seleccionados antes. Sirve para reparar una configuración por capas:

```sshconfig
Host deploy-prod
    SendEnv -*
    SendEnv DEPLOY_REGION BUILD_REF
```

La limpieza afecta a las selecciones acumuladas hasta ese punto. Una inclusión o regla posterior puede volver a añadir nombres. Por eso no uso la sustracción como frontera final. Un archivo dedicado pasado con `-F` tiene menos piezas y produce una configuración que otra persona entiende en una pantalla.

No metas credenciales en este contrato. Un token transferido se convierte en estado normal del proceso remoto y puede llegar a procesos hijos, trazas, informes de fallos, inspección de `/proc` cuando los permisos lo permitan o una ejecución accidental de `env`. SSH protege el transporte, no la vida del valor después de la entrega.

## El servidor debe aceptar nombres exactos para una cuenta limitada

El servidor es el último sitio donde rechazar una variable del cliente antes de iniciar la sesión. OpenSSH no acepta ninguna por defecto, salvo el tratamiento de `TERM` con pseudoterminal. Mantén ese valor global y añade nombres exactos solo para la cuenta propietaria del flujo.

```sshdconfig
Match User deploybot
    AcceptEnv DEPLOY_REGION
    AcceptEnv BUILD_REF
    AcceptEnv WORKFLOW_KIND
```

No uses `AcceptEnv APP_*`, `AcceptEnv AWS_*` ni un comodín desnudo. El manual de `sshd_config` avisa expresamente de que algunas variables pueden eludir entornos de usuario restringidos. Es fácil ignorarlo cuando los nombres actuales parecen inocuos, pero el comodín concede nombres futuros sin otro cambio del servidor.

Un `AcceptEnv` global amplio debilita todas las cuentas coincidentes. Añadir un bloque `Match User` más estrecho no borra nombres ya aceptados globalmente; las entradas pueden acumularse. Si los usuarios interactivos necesitan configuración regional y una cuenta de despliegue no debe recibirla, no empieces con una regla regional global. Limita la excepción a los usuarios o grupos y comprueba cada conexión con `sshd -T -C`.

`SetEnv` del servidor es otro control. Define valores en sesiones hijas y prevalece sobre valores predeterminados o suministrados mediante `AcceptEnv` o `PermitUserEnvironment`. Úsalo cuando el servidor sea dueño de una constante. Si todas las ejecuciones deben usar el mismo valor aprobado por el servidor, configúralo allí en lugar de aceptarlo del cliente.

`PermitUserEnvironment` es otra vía. Controla `~/.ssh/environment` y opciones `environment=` en claves autorizadas, y OpenSSH lo desactiva por defecto. Una auditoría limitada a `AcceptEnv` puede pasarlo por alto. Déjalo apagado salvo que el diseño de una cuenta lo exija; entonces incluye sus patrones en la misma revisión.

Una lista de nombres exactos controla nombres, no valores. Un `DEPLOY_REGION` permitido puede contener espacios, metacaracteres, un salto de línea o una región prohibida. El protocolo lo lleva como datos, pero el script receptor puede convertirlo después en sintaxis mediante `eval`, una expansión sin comillas, una configuración generada o una cadena de orden.

Valida cada valor en el punto de entrada remoto:

```sh
case ${DEPLOY_REGION-} in
    us-east-1|us-west-2) ;;
    *)
        printf 'invalid DEPLOY_REGION\n' >&2
        exit 64
        ;;
esac

case ${BUILD_REF-} in
    [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*)
        ;;
    *)
        printf 'invalid BUILD_REF\n' >&2
        exit 64
        ;;
esac
```

Usa una validación que corresponda al contrato real. El patrón breve ilustra la forma; si una publicación exige un identificador completo, impón su longitud exacta y comprueba que el repositorio lo contiene. No hagas un validador tan permisivo que solo rechace cadenas vacías.

Después de editar, inspecciona el resultado efectivo:

```sh
sudo sshd -t
sudo sshd -T \
  -C user=deploybot,host=deploy.example,addr=192.0.2.44 |
  grep -E '^(acceptenv|permituserenvironment|setenv)'
```

Guarda esta salida con la revisión. Registra lo que el demonio interpretó para la conexión probada, algo más útil que la captura de un fragmento en un directorio lleno de inclusiones.

## Demuestra valores necesarios y señuelos rechazados en remoto

Una prueba útil comprueba casos positivos y negativos dentro del proceso remoto. Asigna marcadores inconfundibles a cada valor requerido, define señuelos que habrían coincidido con patrones antiguos, inicia una sesión no interactiva con el archivo dedicado y haz que el intérprete remoto falle si se incumple el contrato.

Esta secuencia espera del cliente solo `DEPLOY_REGION`, `BUILD_REF` y el valor fijo `WORKFLOW_KIND`:

```sh
export DEPLOY_REGION='env-audit-region'
export BUILD_REF='env-audit-ref'
export AWS_PROFILE='must-not-cross'
export LC_AUDIT_CANARY='must-not-cross'
export APP_PRIVATE_PATH='must-not-cross'

ssh -F ./deploy-ssh.conf -T deploy-prod 'sh -s' <<'REMOTE'
set -eu

test "$(printenv DEPLOY_REGION)" = 'env-audit-region'
test "$(printenv BUILD_REF)" = 'env-audit-ref'
test "$(printenv WORKFLOW_KIND)" = 'deploy'

for name in AWS_PROFILE LC_AUDIT_CANARY APP_PRIVATE_PATH; do
    if printenv "$name" >/dev/null 2>&1; then
        printf 'unexpected forwarded variable: %s\n' "$name" >&2
        exit 1
    fi
done

printf '%s\n' 'SSH environment contract passed'
REMOTE
```

La salida esperada es una línea:

```text
SSH environment contract passed
```

Haz una segunda prueba negativa eliminando un valor local obligatorio. `SendEnv` no puede enviar un nombre ausente, así que la aserción remota debe fallar:

```sh
unset BUILD_REF
if ssh -F ./deploy-ssh.conf -T deploy-prod 'test -n "$BUILD_REF"'; then
    printf '%s\n' 'test failed: BUILD_REF appeared unexpectedly' >&2
    exit 1
fi
```

Esto distingue un valor opcional de una entrada necesaria. Si la tarea debe fallar sin `BUILD_REF`, falla también antes de SSH con `${BUILD_REF:?BUILD_REF is required}`. La comprobación remota sigue siendo necesaria porque verifica el transporte y detecta un rechazo del servidor.

Los señuelos deben cubrir cada comodín o clase dudosa encontrada. Usa valores obviamente falsos. Nunca pongas una credencial real en una prueba de filtración: un fallo puede imprimirla en los registros mientras confirma el riesgo.

Una ejecución correcta no demuestra que ninguna variable imaginable pueda cruzar. Demuestra los casos negativos nombrados bajo una configuración y un entorno. Combínala con dos controles estáticos: `ssh -G` solo debe contener nombres exactos y `sshd -T -C` solo los `AcceptEnv` previstos. Si aparece `*` o `?`, ninguna matriz puede enumerar lo que añadirá un entorno futuro.

Ejecuta la prueba desde cada iniciador distinto. Un intérprete de desarrollador, un trabajador de CI, una tarea del editor y un agente autónomo pueden invocar el mismo binario con rutas y entornos distintos. Registra la ruta del archivo dedicado en el iniciador, no en un alias interactivo.

También hay diferencia entre observar el entorno final y demostrar la contribución SSH. Si `/etc/profile` define `DEPLOY_REGION=us-east-1` y el cliente envía lo mismo, la aserción pasa aunque el servidor lo rechace. Usa marcadores únicos que no existan en la base remota y ejecuta el caso de entrada ausente. Juntos descubren un valor obligatorio rechazado y un valor remoto de reserva.

La prueba no afirma que el entorno remoto solo contenga tres variables. Una sesión normal recibe `HOME`, `USER`, `SHELL`, `PATH` y metadatos SSH, y los inicios o envoltorios pueden añadir más. La aserción prueba que la parte aportada por el cliente coincide con el contrato. Audita aparte la base del servidor si la orden necesita un entorno total mínimo.

## Construir la orden puede evitar SendEnv por completo

Vaciar `SendEnv` no impide que un intérprete expanda variables locales dentro de la cadena remota. Esta es otra ruta de datos:

```sh
ssh deploy-prod "release '$TENANT' '$TOKEN'"
```

El intérprete local sustituye ambos valores antes de ejecutar `ssh`. Viajan dentro de la petición cifrada de orden, no en una petición `env`, por lo que `AcceptEnv` no puede rechazarlos. También pueden aparecer en inspección de procesos, historial, registros de CI o errores según cómo se construya y registre la orden.

Este prefijo afecta al proceso SSH local, pero solo cruza si la configuración selecciona el nombre:

```sh
DEPLOY_REGION=west ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release
```

Los equipos confunden ambos casos. Que estuviera en el entorno cuando se ejecutó SSH no prueba que se transfiriera; desactivar `SendEnv` tampoco prueba que un envoltorio no lo interpolara en argumentos o entrada estándar. Sigue el canal real.

El código de inicio remoto crea otra fuente. Un intérprete, `/etc/environment`, PAM, una orden forzada, `sudo`, un gestor de servicios o un contenedor pueden quitar, reemplazar o añadir valores después de que SSH los acepte. Si falta un marcador, usa `ssh -vvv` para ver decisiones del cliente, los registros permitidos del servidor y una orden mínima anterior al envoltorio. No amplíes `AcceptEnv` de inmediato: suele ocultar la capa que cambió el valor.

`sudo` merece una revisión propia. Según sudoers, puede reiniciar el entorno, conservar nombres o permitir que se solicite su conservación. Eso solo cambia lo que llega al hijo privilegiado. El valor ya llegó a la sesión SSH sin privilegios, donde scripts, ganchos y envoltorios pudieron verlo. Configura sudoers para la orden privilegiada, pero limita SSH antes de esa capa.

El host remoto tampoco es una tubería pasiva. Quien controla la cuenta suele poder imprimir su entorno, y un administrador controla la máquina. Transferir un valor lo revela al dominio remoto por diseño. Si tu argumento exige que el host nunca conozca un valor, no lo envíes mediante SSH de ninguna forma.

Evita volcados de `env` en registros habituales. Durante una auditoría autorizada, captura primero nombres y revela valores solo para marcadores falsos. Un volcado completo convierte variables ajenas en material de auditoría y puede crear el incidente que intentabas evitar.

## El SSH ejecutado por agentes necesita un límite de proceso menor

Un agente autónomo suele heredar el entorno del terminal, editor u orquestador que lo inició. Ese entorno se preparó para una persona que trabaja con varios repositorios y cuentas. Enviar sus espacios de nombres al host da al agente más contexto y a las herramientas remotas entradas que nadie revisó.

Inicia el flujo con un entorno local explícito y un archivo SSH explícito. Un envoltorio mínimo puede exigir los dos valores cambiantes, descartar el estado heredado y restaurar solo lo que necesita el cliente:

```sh
#!/bin/sh
set -eu
: "${DEPLOY_REGION:?DEPLOY_REGION is required}"
: "${BUILD_REF:?BUILD_REF is required}"

exec env -i \
  HOME="$HOME" \
  PATH='/usr/bin:/bin:/usr/sbin:/sbin' \
  DEPLOY_REGION="$DEPLOY_REGION" \
  BUILD_REF="$BUILD_REF" \
  ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release
```

Ajusta `PATH` y las entradas necesarias al sistema operativo y mantén la lista explícita. `HOME` aparece porque OpenSSH puede necesitar archivos de usuario, como hosts conocidos y la ruta de identidad. Si un ejecutor gestionado los proporciona de otro modo, quita también `HOME`.

Para SSH operado por agentes en un Mac, Sallyport puede mantener la clave SSH en su almacén cifrado y ejecutar mediante `sp-ssh`, de modo que el agente no recibe la credencial. Eso cambia la custodia, pero no excusa un contrato vago; conserva la prueba de nombres exactos alrededor de la orden permitida.

No transfieras credenciales locales de nube como atajo. Si la acción remota necesita otro servicio, dale una identidad propia y limitada o enrútala por una pasarela que guarde la credencial. Copiar la credencial ambiental del operador a un proceso remoto une fronteras de confianza y complica la revocación.

## Mantén el contrato ejecutable cuando cambie la configuración

Las reglas de entorno derivan porque los paquetes añaden valores, los administradores consolidan fragmentos y los flujos adquieren entradas. Una norma escrita no detectará esa deriva. Revisa juntos el archivo dedicado, la configuración de cuenta y la aserción de señuelos.

Ejecuta la aserción tras cambios en estas superficies:

- Paquetes del cliente SSH o del sistema operativo
- Inclusiones de configuración de usuario y sistema
- `sshd_config`, PAM, inicios del intérprete u órdenes forzadas
- El iniciador del agente, ejecutor de CI, gestor de servicios o imagen
- La lista de entradas requeridas por el flujo

Trata una variable nueva como un cambio de interfaz. Documenta por qué la necesita la orden, quién posee el valor, si contiene contexto sensible y qué prueba demuestra su ausencia en otros sitios. Si nadie responde, pásala como entrada validada o rediseña la acción en vez de ampliar un comodín.

Haz que el fallo sea evidente. Un despliegue que recurre a un valor remoto por defecto cuando se rompe la transferencia es más difícil de diagnosticar y más fácil de usar mal que uno que se detiene. Las entradas obligatorias deben fallar en el iniciador local y en el punto remoto.

Por último, revisa la cuenta desde el lado remoto. Una lista perfecta no protege una cuenta que ejecuta intérpretes arbitrarios, lee entornos ajenos o reescribe sus inicios. La transferencia es un canal de entrada. Hazlo exacto, demuestra su conducta y limita la autoridad de la orden para que un valor inesperado no se convierta en otra acción.
