Seguridad Bash
El sistema de seguridad Bash opera con 5 capas independientes de defensa en profundidad. Aunque una capa sea eludida, las demás continúan bloqueando ataques — desde validadores de inyección y restricciones de rutas hasta aislamiento en sandbox y limpieza de variables de entorno.
Arquitectura — 5 Capas
Pipeline de Ejecución de Comandos
Variables de entorno inyectadas
| SHELL | Ruta del binario del shell |
| GIT_EDITOR | 'true' — previene editores git interactivos |
| CLAUDECODE | '1' — señaliza a CLIs que están dentro de Claude Code |
| CLAUDE_CODE_SESSION_ID | ID de sesión (solo usuarios internos) |
Sistema de timeouts
sleep está en DISALLOWED_AUTO_BACKGROUND_COMMANDS — nunca se manda al fondoValidadores de Seguridad (22+)
Validadores tempranos (cortocircuito en allow)
| # | Validador | Qué captura |
|---|---|---|
| 1 | validateEmpty | Comandos vacíos → allow |
| 2 | validateIncompleteCommands | Fragmentos que empiezan con tabs, flags, operadores |
| 3 | validateSafeCommandSubstitution | Patrones seguros heredoc-in-substitution |
| 4 | validateGitCommit | git commit con mensajes simples entre comillas |
Validadores principales — ataques de misparsing
| # | Validador | Qué captura |
|---|---|---|
| 5 | validateJqCommand | system(), -f/--from-file |
| 6 | validateObfuscatedFlags | Caracteres entre comillas en nombres de flags |
| 7 | validateShellMetacharacters | ;, |, & en argumentos |
| 8 | validateDangerousVariables | Variables en contextos de redirección/pipe |
| 9 | validateCommentQuoteDesync | # causando desincronización en seguimiento de comillas |
| 10 | validateQuotedNewline | Saltos de línea dentro de comillas que dividen comandos |
| 11 | validateCarriageReturn | Diferencial de tokenización CR shell-quote / bash |
| 12 | validateNewlines | Saltos de línea separando comandos (no misparsing) |
| 13 | validateIFSInjection | Uso de variable $IFS |
| 14 | validateProcEnvironAccess | Acceso a /proc/*/environ |
| 15 | validateDangerousPatterns | Backticks, $(), $${}, $[], expansiones Zsh |
| 16 | validateRedirections | Redirecciones de entrada < y salida > (no misparsing) |
| 17 | validateBackslashEscapedWhitespace | Bypasses con barra invertida-espacio |
| 18 | validateBackslashEscapedOperators | \;, \| etc. |
| 19 | validateUnicodeWhitespace | Caracteres de espacio no ASCII |
| 20 | validateMidWordHash | # adyacente a comillas |
| 21 | validateBraceExpansion | Patrones de expansión de llaves {a,b} |
| 22 | validateZshDangerousCommands | zmodload, emulate, sysopen, etc. (20 cmds) |
| 23 | validateMalformedTokenInjection | Delimitadores desbalanceados + separadores (bypass eval en HackerOne) |
Misparsing vs no-misparsing
Validadores de misparsing Sus resultados ask activan isBashSecurityCheckForMisparsing: true, causando bloqueo temprano en el flujo de permisos. Capturan ataques que explotan diferencias entre cómo el parser de seguridad y bash real tokenizan comandos.
Validadores no-misparsing validateNewlines y validateRedirections — sus resultados se difieren para que los validadores de misparsing se ejecuten primero.
Extracción de comillas — 3 vistas
Vista Qué hace withDoubleQuotes Contenido entre comillas simples eliminado, dobles preservadas fullyUnquoted Todo el contenido entre comillas eliminado unquotedKeepQuoteChars Contenido eliminado pero delimitadores de comillas preservados
Eliminación de redirecciones seguras
stripSafeRedirections() elimina patrones conocidos como seguros:
✓ 2>&1 (stderr a stdout) ✓ >/dev/null o 2>/dev/null ✓ </dev/null (stdin vacío) Cada patrón requiere límite final (?=\s|$) para prevenir ataques de prefijo (ej. >/dev/nullo escribiría en el archivo nullo).
Flujo de Permisos y Comandos de Solo Lectura
bashToolHasPermission() — pipeline de 8 pasos
1. checkPermissionMode() — acceptEdits → auto-allow mkdir, touch, rm, etc. 2. checkReadOnlyConstraints() — Parsear comando → si es solo lectura → allow 3. bashCommandIsSafeAsync() — Ejecutar 22+ validadores → cualquier "ask" → bloquear con razón 4. checkPathConstraints() — Extraer rutas → validar dentro de directorios permitidos 5. checkSedConstraints() — Manejo especial para sed -i ediciones in-place 6. Coincidencia de reglas — Verificar reglas allow (prefijo), verificar reglas deny 7. Sandbox auto-allow — Si sandboxed + autoAllowBashIfSandboxed → allow 8. Clasificador ML (feature-gated) — Solo ANT: modelo clasificador bash → allow/deny Manejo de comandos compuestos
Comandos con &&, ||, ;, | se dividen mediante splitCommand_DEPRECATED(). Límite de 50 subcomandos previene agotamiento de CPU. Si algún subcomando falla → todo el comando es bloqueado.
Lista de comandos de solo lectura
Operaciones de archivo: ls, cat, head, tail, wc, file, stat, du, df, find, tree, realpath, md5sum, sha256sum, xxd Procesamiento de texto: grep, rg, awk, sed (sin -i), sort, uniq, cut, tr, diff, comm, jq, yq, xq, column Git (lectura): git status, git log, git diff, git show, git branch, git tag, git blame, git shortlog Desarrollo: node -e, python -c, tsc --noEmit, eslint, prettier --check, cargo check, go vet Sistema: echo, printf, date, env, which, type, uname, hostname, whoami, id, pwd, test Validación de flags por comando
fd -x / -X — excluido: --exec / --exec-batch ejecutan código fd -l — excluido: ejecuta subprocess ls internamente (riesgo de secuestro de PATH) jq — bloquea system(), -f, --from-file sed -i — edición in-place: NO es solo lectura, requiere permiso explícito Validación de Rutas y Protección del Sistema de Archivos
Extractores de rutas por comando (30+ comandos)
Comandos Estrategia de extracción cd, ls, cat, head, tail Args posicionales tras eliminar flags rm, rmdir, mkdir, touch Todos los argumentos que no son flags mv, cp Argumentos de origen y destino find Primer argumento (raíz de búsqueda) grep, rg Args de archivo después del patrón sed Archivo objetivo de -i git Extracción específica por subcomando jq Argumento de archivo de entrada
Manejo de POSIX -- fin de opciones
filterOutFlags() maneja correctamente --: después de él, TODOS los argumentos se tratan como rutas, previniendo:
rm -- -/../.claude/settings.local.json
# "-/../.claude/..." es una RUTA, capturada como traversal
Archivos y directorios protegidos
Archivos protegidos (edición automática bloqueada)
.gitconfig, .gitmodules, .bashrc, .bash_profile, .zshrc, .zprofile, .profile, .ripgreprc, .mcp.json, .claude.json
Directorios protegidos
.git, .vscode, .idea, .claude
Config de Claude (protección extra)
.claude/settings.json, .claude/settings.local.json, .claude/commands/, .claude/agents/, .claude/skills/
Verificaciones de seguridad de rutas
Verificación Qué captura NTFS ADS : después de posición 2 (flujos de datos alternativos) Nombres cortos 8.3 Patrones ~\d (nombres cortos Windows) Prefijos de ruta larga \\?\, \\.\ (rutas extendidas Windows) Nombres de dispositivo DOS CON, PRN, AUX, NUL, etc. Tres puntos ... en componentes de ruta Resolución de symlinks Se verifican tanto la ruta original COMO el destino resuelto Normalización de mayúsculas normalizeCaseForComparison() en minúsculas en todas partes
Sandbox y Seguridad de Entorno
Plataformas sandbox
Plataforma Tecnología Estado macOS seatbelt (sandbox-exec) Integrado Linux bubblewrap (bwrap) Requiere instalación WSL2 bubblewrap Requiere instalación Windows nativo — No soportado
Flujo de decisión del sandbox
1. ¿Sandboxing habilitado? → No → sin sandbox 2. dangerouslyDisableSandbox: true + areUnsandboxedCommandsAllowed() → sin sandbox 3. ¿Comando en lista excludedCommands? → sin sandbox 4. Aplicar SandboxManager.wrapWithSandbox() excludedCommands NO es un límite de seguridad — la seguridad viene del sistema de permisos.
Defensa contra repositorios git bare
El sandbox bloquea escrituras en archivos estructurales de git en CWD: HEAD, objects/, refs/, hooks/, config. Post-ejecución, scrubBareGitRepoFiles() elimina cualquier archivo plantado. Previene que atacantes coloquen git hooks maliciosos.
Limpieza del entorno de subprocesos
Activado cuando CLAUDE_CODE_SUBPROCESS_ENV_SCRUB está configurado (contexto GitHub Actions):
Categoría Variables eliminadas Anthropic ANTHROPIC_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_AUTH_TOKEN AWS AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_BEARER_TOKEN_BEDROCK GCP/Azure Variables de credenciales GCP/Azure GitHub Actions ACTIONS_ID_TOKEN_REQUEST_TOKEN, tokens de runtime OTEL Headers que pueden contener tokens de autenticación INPUT_* Todas las variantes con prefijo INPUT_ de lo anterior
Variables que NUNCA se pueden eliminar
Categoría Variables Riesgo Ejecución PATH, LD_PRELOAD, LD_LIBRARY_PATH, DYLD_* Secuestro de binarios/librerías Carga de módulos PYTHONPATH, NODE_PATH, CLASSPATH, RUBYLIB Inyección de código via imports Ejecución de código GOFLAGS, RUSTFLAGS, NODE_OPTIONS Código arbitrario via flags Sistema HOME, TMPDIR, SHELL, BASH_ENV Modificación de comportamiento
Patrones Peligrosos, PowerShell y Avisos Destructivos
Patrones de comandos peligrosos
Multi-plataforma (ejecución de código)
python, python3, node, deno, tsx, ruby, perl, php, lua, npx, bunx, npm run, yarn run, bash, sh, ssh
Adiciones Unix
zsh, fish, eval, exec, env, xargs, sudo
Específicos de Zsh (20 builtins)
zmodload, emulate, sysopen, syswrite, ztcp, zsocket, zf_rm, zf_mkdir, zf_rmdir, zf_ln, zf_mv, zf_chmod…
Avisos de comandos destructivos
Git: git reset --hard, git push --force, git clean -f, git checkout ., git stash drop/clear, git branch -D, git commit --amend Sistema de archivos: rm -rf, rm -r, rm -f Base de datos: DROP TABLE/DATABASE, TRUNCATE TABLE, DELETE FROM Infraestructura: kubectl delete, terraform destroy Son avisos informativos en el diálogo de permisos — no son bloqueos de seguridad.
Seguridad PowerShell (sistema paralelo)
Espejo del sistema Bash con adaptaciones específicas de plataforma: CmdletPathConfig por cmdlet, coincidencia case-insensitive, GIT_SAFETY_WRITE_CMDLETS, detección de extractores de archivos.
Patrones peligrosos PowerShell
pwsh, powershell, cmd, wsl, iex, invoke-expression, start-process, saps, start-job, sajb, register-objectevent
Categorías bloqueadas en modo auto PowerShell (4)
1 Descarga y Ejecución: iex (iwr ...) — equivalente a curl | bash 2 Destrucción Irreversible: Remove-Item -Recurse -Force — equivalente a rm -rf 3 Persistencia: Modificar $PROFILE, Register-ScheduledTask, claves Run del registro 4 Elevación: Start-Process -Verb RunAs, -ExecutionPolicy Bypass, deshabilitar AMSI/Defender 12 Principios de Diseño de Seguridad
1. Defensa en Profundidad Múltiples capas independientes bloquean ataques. Eludir una capa no compromete las demás.
2. Valores Seguros por Defecto Parámetros desconocidos, fallos de parseo y comandos complejos → ask. El sistema nunca asume seguridad.
3. Consciencia del Misparsing Los validadores tienen en cuenta diferencias entre la tokenización del parser de seguridad y bash real.
4. Rutas Case-Insensitive normalizeCaseForComparison() aplicado en todas partes para prevenir bypasses en macOS/Windows.
5. Resolución de Symlinks Tanto la ruta original COMO el destino resuelto se verifican para todas las decisiones de seguridad.
6. Sin Confianza en Controles de Usuario excludedCommands explícitamente NO es un límite de seguridad — la seguridad viene del sistema de permisos.
7. Limpieza de Entorno API keys y tokens CI eliminados de entornos de subprocesos en contextos GitHub Actions.
8. Defensa contra Git Bare Sandbox bloquea escrituras en archivos estructurales de git. Limpieza post-ejecución elimina archivos plantados.
9. Nonces por Proceso La raíz de skills usa randomBytes(16) para prevenir ataques de pre-creación en directorios /tmp compartidos.
10. División de Comandos Compuestos Operadores &&, ||, ;, | parseados — cada subcomando validado de forma independiente. Límite de 50 previene agotamiento CPU.
11. Seguimiento de Contexto de Comillas 3 vistas de cada comando permiten detectar con precisión metacaracteres ocultos en contextos entre comillas.
12. Aserciones de Límites La eliminación segura de redirecciones requiere límites finales (?=\s|$) para prevenir ataques de prefijo.
i Manejo de salida
Los resultados de herramientas con más de 30.000 caracteres se persisten en archivo; 64 MB es el tamaño máximo persistido.
El EndTruncatingAccumulator conserva el inicio y el final de la salida, truncando el medio con
[... truncated ...]. Las salidas grandes incluyen una vista previa con un puntero al archivo completo para la herramienta Read.