T09 · Insecure Skill Coding Practices
- Location
vault.sh:25- Finding
SSH Option Injection Through Unvalidated Connection Parameters
- Content
View full analysis
&2 exit 1 fi # Run vaultctl command on remote Mac run_vaultctl() { ssh $SSH_OPTS -p "$VAULT_SSH_PORT" "${VAULT_SSH_USER}@${VAULT_SSH_HOST}" vaultctl "$@" } ``` The related instruction in `SKILL.md` directly interpolates the same parameters: ```bash ssh -4 -p ${VAULT_SSH_PORT:-2222} ${VAULT_SSH_USER}@${VAULT_SSH_HOST:-localhost} vaultctl [args] ``` ### Technical Analysis The script accepts the SSH username, host, and port from environment variables, with the username also optionally loaded from a configuration file. These values are not validated before being passed to OpenSSH. Although the combined destination is shell-quoted in `vault.sh`, quoting only prevents shell word splitting and expansion. It does not stop the `ssh` executable from interpreting an argument beginning with `-` as an SSH option. If `VAULT_SSH_USER` begins with an option such as `-oProxyCommand=`, the resulting destination argument can be parsed as an SSH option instead of as `[user@]hostname`. OpenSSH's `ProxyCommand` option invokes a local command through a shell, creating a local command-execution primitive. For example, a maliciou ...[truncated 2384 chars]- Remediation
View remediation
&2 exit 1 fi if [[ ! "$VAULT_SSH_HOST" =~ ^[A-Za-z0-9.-]+$ ]] || [[ "$VAULT_SSH_HOST" == -* ]]; then echo '{"error":"invalid_config","message":"Invalid SSH host"}' >&2 exit 1 fi if [[ ! "$VAULT_SSH_PORT" =~ ^[0-9]+$ ]] || (( VAULT_SSH_PORT < 1 || VAULT_SSH_PORT > 65535 )); then echo '{"error":"invalid_config","message":"Invalid SSH port"}' >&2 exit 1 fi ``` 2. **Use an array for fixed SSH options.** ```bash SSH_OPTS=( -4 -o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=yes ) run_vaultctl() { local destination="${VAULT_SSH_USER}@${VAULT_SSH_HOST}" ssh "${SSH_OPTS[@]}" -p "$VAULT_SSH_PORT" -- \ "$destination" vaultctl "$@" } ``` Use `--` only after verifying that the deployed OpenSSH client supports it. Input validation remains required because compatibility and parsing behavior can vary. 3. **Prefer fixed connection settings.** If the intended architecture always uses a local reverse tunnel, hard-code or enforce `VAULT_SSH_HOST=localhost` rather than accepting an arbitrary host. 4. **Secure the fallback configuration file.** - Require it to be owned by the current user. - Reject group- or world-writable files. - Read only a single validated line. - Avoid following untrusted symlinks where practical. 5. **Update `SKILL.md`.** Remove d ...[truncated 543 chars]
