0Pricing
Linux Command Line & Bash Scripting Mastery · Lección

Gestión segura de secretos e higiene del entorno

Mantenga las credenciales fuera de las listas de procesos y los registros mediante stdin, archivos y entornos depurados.

Gestión segura de secretos e higiene del entorno es una lección gratuita de Linux Command Line & Bash Scripting Mastery en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Linux Command Line & Bash Scripting Mastery, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Linux Command Line & Bash Scripting Mastery incluye 4 lecciones en total.

Por qué es importante proteger los secretos

Los secretos —claves de API, contraseñas y tokens— son los datos más sensibles de cualquier sistema. Gestionarlos incorrectamente en scripts de Bash es uno de los errores de seguridad más habituales y dañinos.

  • Listados de procesos: los argumentos pasados a los comandos aparecen en ps aux, /proc/<pid>/cmdline y los registros de auditoría del sistema, visibles para todos los usuarios del host.
  • Historial del shell: los comandos escritos de forma interactiva (y, en ocasiones, los scripts) se registran en ~/.bash_history.
  • Archivos de registro: las trazas de set -x, los registros de la aplicación y la salida de CI/CD pueden capturar valores de variables.
  • Fuga a través del entorno: los procesos secundarios heredan todo el entorno de su proceso padre, incluidos los secretos exportados.

Un script reforzado trata los secretos como material radiactivo: minimiza el tiempo de exposición, limita la superficie expuesta y sanitiza todo al salir.

La superficie de ataque de los listados de procesos

Cuando pasa un secreto como argumento de línea de comandos, cualquier usuario del sistema puede leerlo inmediatamente mediante ps. No es una posibilidad teórica: se explota habitualmente en entornos de hosting compartido y contenedores.

El fragmento siguiente muestra el problema y la solución uno al lado del otro.

#!/usr/bin/env bash
# DANGEROUS: password visible in 'ps aux' output
# curl -u "admin:SuperSecret123" https://api.example.com/data

# SAFE: pass credentials via stdin or a flag that reads from a file
# Many tools support reading secrets from stdin with '-' or dedicated flags:

# Option 1 — pipe the secret so it never appears in argv
echo 'SuperSecret123' | curl -u 'admin' --password-stdin \
  https://api.example.com/data 2>/dev/null || true

# Option 2 — write a temporary netrc and point curl at it
# (covered in a later scene)
echo 'Secret never touches the command line this way'

Lectura de secretos desde stdin

El patrón interactivo más seguro consiste en leer un secreto durante la ejecución mediante read -rs. El flag -s suprime el eco para que los caracteres no se muestren nunca, y -r impide interpretar las barras invertidas.

Aspectos clave:

  • La variable nunca se exporta, por lo que los procesos secundarios no pueden verla mediante /proc/<pid>/environ.
  • Después de usarla, haga unset de la variable inmediatamente para reducir la ventana de exposición.
  • Evite echo "$SECRET": use printf '%s' para impedir que un salto de línea final corrompa el valor y para que este permanezca invisible en las trazas.
#!/usr/bin/env bash
set -euo pipefail

# Prompt on stderr so stdout stays clean for piping
read -rsp 'Enter API token: ' API_TOKEN <&2
printf '\n' >&2

# Use the secret — printf keeps it out of argv
response=$(printf '%s' "$API_TOKEN" | curl -sS -X POST \
  -H 'Content-Type: application/json' \
  --data-binary @- \
  https://httpbin.org/post 2>/dev/null) || true

echo "Request sent."

# Scrub immediately — unset removes it from shell memory
unset API_TOKEN

Secretos en archivos: permisos y propiedad

Cuando un secreto debe persistir en el disco (por ejemplo, una clave de cuenta de servicio), los permisos del archivo son su principal defensa.

  • Modo 0600 — solo el propietario puede leerlo y escribirlo. Sin acceso para el grupo ni para otros usuarios.
  • Modo 0400 — solo el propietario puede leerlo. Prefiéralo para claves que nunca debería sobrescribir accidentalmente.
  • Almacene los archivos secretos en un directorio específico, como ~/.secrets/ o /run/secrets/ (este último es un tmpfs respaldado por RAM en muchos sistemas Linux y solo persiste hasta el reinicio).
  • Nunca coloque archivos secretos dentro de un directorio seguido por git sin un .gitignore totalmente confiable.
#!/usr/bin/env bash
set -euo pipefail

SECRETS_DIR="${HOME}/.secrets"
mkdir -p "$SECRETS_DIR"
chmod 700 "$SECRETS_DIR"   # directory: only owner can list contents

KEY_FILE="${SECRETS_DIR}/api_token"

# Write secret — atomically restrict permissions before writing content
install -m 0600 /dev/null "$KEY_FILE"
printf '%s' 'my-super-secret-token' > "$KEY_FILE"

echo "Permissions:"
ls -la "$KEY_FILE"

# Read back safely — no subshell, no echo
API_TOKEN=$(< "$KEY_FILE")
echo "Token length: ${#API_TOKEN} chars (value not printed)"
unset API_TOKEN

Uso de un archivo .netrc con curl

curl admite un archivo ~/.netrc (o una ruta arbitraria mediante --netrc-file) que asigna nombres de host a credenciales. Esto mantiene los datos de autenticación completamente fuera de la línea de comandos y del cuerpo del script.

El formato del archivo es sencillo:

machine api.example.com
  login admin
  password s3cr3t

Buenas prácticas:

  • Establezca siempre chmod 0600 ~/.netrc: en algunos sistemas, curl rechaza el archivo si otros usuarios pueden leerlo.
  • Use --netrc-file /run/secrets/netrc para apuntar a un secreto respaldado por tmpfs o inyectado en un contenedor.
  • Elimine los archivos netrc temporales con un trap en EXIT.
#!/usr/bin/env bash
set -euo pipefail

TMP_NETRC=$(mktemp)
chmod 0600 "$TMP_NETRC"

# Trap ensures cleanup even on error or signal
trap 'rm -f "$TMP_NETRC"' EXIT

# Write credentials to the temp netrc
cat > "$TMP_NETRC" <<'EOF'
machine httpbin.org
  login myuser
  password mypassword
EOF

curl -fsS --netrc-file "$TMP_NETRC" \
  https://httpbin.org/basic-auth/myuser/mypassword \
  -o /dev/null -w 'HTTP %{http_code}\n' || true

# trap fires here: $TMP_NETRC is deleted
echo 'Temp netrc cleaned up by trap.'

Higiene de las variables de entorno

Las variables de entorno son una forma habitual de inyectar secretos en scripts (aplicaciones de 12 factores y canalizaciones de CI/CD). Sin embargo, se filtran a cada proceso hijo y aparecen en /proc/<pid>/environ durante toda la vida del proceso.

Patrones defensivos:

  • Importe el secreto inmediatamente en una variable local y elimine la variable de entorno con unset para impedir que los procesos hijos la hereden.
  • Pase los secretos a comandos específicos mediante env -i o una asignación en línea, en lugar de usar todo el entorno heredado.
  • Nunca use export con una variable secreta: cuando sea posible, asígnela únicamente (sin export).
#!/usr/bin/env bash
set -euo pipefail

# Simulate a secret arriving via environment (e.g., from CI system)
export DB_PASSWORD='hunter2'   # set by CI — we did not choose this

# Capture locally, then strip from environment immediately
db_password="$DB_PASSWORD"
unset DB_PASSWORD

# Verify the env var is gone before spawning any child process
if printenv DB_PASSWORD 2>/dev/null; then
  echo 'ERROR: DB_PASSWORD still in environment!' >&2
  exit 1
fi

echo 'Secret captured and env var scrubbed.'
echo "Password length: ${#db_password}"
unset db_password

Cómo evitar que los secretos aparezcan en los rastreos de set -x

set -x (xtrace) es muy útil para depurar, pero imprime en stderr el valor de cada variable que expande, incluidos los secretos. Estos rastreos suelen terminar en registros de CI o en syslog.

Estrategias para proteger los secretos y mantener la utilidad del rastreo:

  • Desactive temporalmente el rastreo alrededor de las operaciones sensibles con { set +x; } 2>/dev/null.
  • Vuelva a activarlo después con set -x.
  • Redirija la salida de xtrace a un descriptor de archivo independiente que apunte a un archivo de registro protegido, no al flujo de registros público.
#!/usr/bin/env bash
set -euo pipefail
set -x   # tracing ON — safe for non-sensitive sections

echo 'Building application...'
SRC_DIR='/tmp/build'
mkdir -p "$SRC_DIR"

# Disable xtrace around secret handling (suppress the set +x line itself)
{ set +x; } 2>/dev/null

read -rsp 'Token (hidden from trace): ' SECRET_TOKEN <&2
printf '\n' >&2
token_len=${#SECRET_TOKEN}
unset SECRET_TOKEN

set -x  # tracing back ON

echo "Token captured (length=$token_len). Continuing build..."
ls "$SRC_DIR"

Limpieza de secretos en archivos de registro

Incluso si tiene cuidado, a veces los secretos terminan en la salida de registro, especialmente en scripts detallados o heredados. Una función envoltorio de registro que redacte patrones conocidos añade una capa de seguridad.

Este patrón usa un reemplazo basado en expresiones regulares sobre toda la salida de registro. Es una capa de último recurso, no un sustituto de las demás prácticas de higiene ya explicadas.

#!/usr/bin/env bash
set -euo pipefail

# A logging function that scrubs common secret patterns before writing
log() {
  local line
  # Replace anything that looks like key=VALUE or password=VALUE
  line=$(printf '%s\n' "$*" \
    | sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***REDACTED***/gi')
  printf '[%s] %s\n' "$(date -u '+%T')" "$line"
}

# Usage:
log 'Connecting to database with password=hunter2'
log 'Loaded API token=sk-abc123xyz secret'
log 'Build step completed successfully'   # unchanged

Entornos aislados con env -i

env -i inicia un comando con un entorno completamente vacío, lo que impide que las variables heredadas, incluidos los secretos accidentales, lleguen al proceso hijo. Después, pasa explícitamente solo lo necesario.

Resulta especialmente útil al ejecutar scripts que no son de confianza, herramientas de compilación o utilidades de terceros que podrían extraer datos del entorno.

#!/usr/bin/env bash
set -euo pipefail

# Polluted parent environment (simulating a CI runner)
export AWS_SECRET_ACCESS_KEY='AKIAIOSFODNN7EXAMPLE'
export GITHUB_TOKEN='ghp_faketoken123'
export HOME="$HOME"
export PATH="$PATH"

echo '--- Child sees full environment:'
env | grep -E 'AWS|GITHUB' | head -5

echo '--- Sanitised child (env -i) sees nothing secret:'
env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-dumb}" \
  bash -c 'env | grep -E "AWS|GITHUB" || echo "No secrets visible"'

unset AWS_SECRET_ACCESS_KEY GITHUB_TOKEN

Archivos secretos temporales en tmpfs

tmpfs es un sistema de archivos respaldado por RAM. Los archivos escritos allí nunca se vacían al disco, lo que elimina el riesgo de que los secretos permanezcan en la swap, la caché de disco o las instantáneas.

  • En Linux, /dev/shm y /run/user/<uid> suelen ser montajes tmpfs.
  • Combine siempre el uso de tmpfs con un trap EXIT para eliminar los archivos cuando termine el script.
  • En contenedores (Docker, Kubernetes), los secretos pueden montarse como volúmenes tmpfs directamente en /run/secrets.
#!/usr/bin/env bash
set -euo pipefail

# Prefer /run/user/$UID (user-owned tmpfs) or /dev/shm (world-readable dir!)
if [[ -d "/run/user/$UID" ]]; then
  TMPFS_DIR="/run/user/$UID"
elif [[ -d '/dev/shm' ]]; then
  TMPFS_DIR='/dev/shm'
else
  # Fallback: warn that disk will be used
  echo 'WARNING: No tmpfs available; using /tmp (disk-backed)' >&2
  TMPFS_DIR='/tmp'
fi

SECRET_FILE=$(mktemp "${TMPFS_DIR}/secret.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'shred -u "$SECRET_FILE" 2>/dev/null || rm -f "$SECRET_FILE"' EXIT

printf '%s' 'my-runtime-token' > "$SECRET_FILE"
echo "Secret stored in: $SECRET_FILE"
df -T "$SECRET_FILE" | awk 'NR==2 {print "Filesystem type:", $2}'

# Use the secret...
token=$(< "$SECRET_FILE")
echo "Token length: ${#token}"
unset token
# trap fires on exit: file shredded

Integración de todo: un script de implementación reforzado

El siguiente script combina todas las técnicas de esta lección en un asistente de implementación realista. Observe cómo cada capa de defensa refuerza a las demás:

  • Lectura desde stdin con -s: sin mostrar la entrada en el terminal
  • Archivo secreto en tmpfs con limpieza mediante trap
  • Limpieza del entorno: el secreto se elimina antes de cualquier subproceso
  • Protección de xtrace: el rastreo se pausa alrededor del código sensible
  • Redacción de registros: una expresión regular de seguridad antes de escribir en el registro
#!/usr/bin/env bash
set -euo pipefail

### 1. Redacting logger
log() {
  local msg
  msg=$(printf '%s' "$*" \
    | sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***/gi')
  printf '[%s] %s\n' "$(date -u +%T)" "$msg"
}

### 2. tmpfs secret store
TMPFS_DIR="${XDG_RUNTIME_DIR:-/tmp}"
SECRET_FILE=$(mktemp "${TMPFS_DIR}/deploy_token.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'rm -f "$SECRET_FILE"; log "Secret file cleaned up."' EXIT

### 3. Read secret without trace
{ set +x; } 2>/dev/null
read -rsp 'Deploy token: ' _tok <&2; printf '\n' >&2
printf '%s' "$_tok" > "$SECRET_FILE"
unset _tok
set -x

### 4. Scrub inherited env vars before subprocess
unset DEPLOY_TOKEN 2>/dev/null || true

log 'Starting deployment...'
# Simulate deploy using secret from file (token never in argv)
# curl -H "Authorization: Bearer $(< $SECRET_FILE)" https://api.example.com/deploy
log 'Deployment complete. token=hidden_by_redactor'

echo 'Done.'

Comprobación de conocimientos: exposición de secretos mediante la lista de procesos

Compruebe su comprensión de cómo se filtran los secretos a través de las listas de procesos y cómo evitarlo.

Resumen de la lección: gestión segura de secretos

Ha completado Gestión segura de secretos e higiene del entorno. Este es un resumen conciso de todo lo tratado:

  • Listas de procesos: nunca pase secretos como argumentos de la línea de comandos: aparecen en ps aux y /proc/<pid>/cmdline. Use una canalización por stdin o --netrc-file.
  • Lecturas desde stdin: use read -rs para recopilar secretos de forma interactiva sin mostrar la entrada en el terminal ni exponerla al historial del shell.
  • Permisos de archivos: los archivos secretos deben tener chmod 0600 (o 0400). Use install -m 0600 para una creación atómica.
  • Archivos netrc: delegue las credenciales en un archivo temporal indicado mediante --netrc-file; elimínelo con trap EXIT.
  • Higiene del entorno: ejecute inmediatamente unset sobre las variables de entorno secretas después de capturarlas localmente; nunca las use con export de forma innecesaria; use env -i para aislar los procesos hijos.
  • Protección de xtrace: envuelva el código sensible en { set +x; } 2>/dev/null ... set -x para impedir que los rastreos de depuración filtren valores.
  • Redacción de registros: use un registrador basado en sed como red de seguridad de último recurso.
  • tmpfs: almacene los secretos de ejecución en /run/user/$UID o /dev/shm para que nunca lleguen al disco; elimínelos de forma segura al salir.

La defensa en profundidad es la mentalidad clave: ninguna medida aislada es suficiente, pero combinarlas dificulta enormemente la filtración de secretos.

Preguntas frecuentes

¿La lección «Gestión segura de secretos e higiene del entorno» es gratis?

Sí — el texto completo de «Gestión segura de secretos e higiene del entorno» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Linux Command Line & Bash Scripting Mastery, actualiza a CoddyKit PRO. El curso de Linux Command Line & Bash Scripting Mastery incluye 4 lecciones en total.

¿Qué aprenderé en «Gestión segura de secretos e higiene del entorno»?

Mantenga las credenciales fuera de las listas de procesos y los registros mediante stdin, archivos y entornos depurados. Practicas Linux Command Line & Bash Scripting Mastery con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Linux Command Line & Bash Scripting Mastery?

No se requiere experiencia previa. Linux Command Line & Bash Scripting Mastery en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Gestión segura de secretos e higiene del entorno»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Linux Command Line & Bash Scripting Mastery?

Sí. Cada lección de Linux Command Line & Bash Scripting Mastery incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Prevención de inyección de comandos y argumentos
  2. Gestión segura de secretos e higiene del entorno
  3. Ejecución con mínimos privilegios y disciplina con sudo
  4. Análisis estático y auditoría con ShellCheck
← Volver a Linux Command Line & Bash Scripting Mastery