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>/cmdliney 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": useprintf '%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_TOKENSecretos 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
.gitignoretotalmente 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_TOKENUso 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 s3cr3tBuenas prácticas:
- Establezca siempre
chmod 0600 ~/.netrc: en algunos sistemas, curl rechaza el archivo si otros usuarios pueden leerlo. - Use
--netrc-file /run/secrets/netrcpara apuntar a un secreto respaldado por tmpfs o inyectado en un contenedor. - Elimine los archivos netrc temporales con un
trapen 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 -io una asignación en línea, en lugar de usar todo el entorno heredado. - Nunca use
exportcon una variable secreta: cuando sea posible, asígnela únicamente (sinexport).
#!/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_passwordCó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' # unchangedEntornos 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_TOKENArchivos 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/shmy/run/user/<uid>suelen ser montajes tmpfs. - Combine siempre el uso de tmpfs con un
trap EXITpara 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 shreddedIntegració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 auxy/proc/<pid>/cmdline. Use una canalización por stdin o--netrc-file. - Lecturas desde stdin: use
read -rspara 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(o0400). Useinstall -m 0600para una creación atómica. - Archivos netrc: delegue las credenciales en un archivo temporal indicado mediante
--netrc-file; elimínelo contrap EXIT. - Higiene del entorno: ejecute inmediatamente
unsetsobre las variables de entorno secretas después de capturarlas localmente; nunca las use conexportde forma innecesaria; useenv -ipara aislar los procesos hijos. - Protección de xtrace: envuelva el código sensible en
{ set +x; } 2>/dev/null ... set -xpara impedir que los rastreos de depuración filtren valores. - Redacción de registros: use un registrador basado en
sedcomo red de seguridad de último recurso. - tmpfs: almacene los secretos de ejecución en
/run/user/$UIDo/dev/shmpara 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
- Prevención de inyección de comandos y argumentos
- Gestión segura de secretos e higiene del entorno
- Ejecución con mínimos privilegios y disciplina con sudo
- Análisis estático y auditoría con ShellCheck