T09 · Insecure Skill Coding Practices
- Location
scripts/habitica.sh:7- Finding
Arbitrary Code Execution Through Sourced Credential Configuration
- Content
View full analysis
Vulnerability Details
File Location:
scripts/habitica.sh, lines 7-13
Vulnerability Type: Unsafe execution of configuration-file contents
Risk Level: HighVulnerable Code
bash CONFIG_FILE="${HABITICA_CONFIG:-$HOME/.habitica}" # Load credentials load_creds() { if [[ -f "$CONFIG_FILE" ]]; then source "$CONFIG_FILE" fiTechnical Analysis
The script loads credentials by passing the configuration file to the Bash
sourcebuilt-in.sourcedoes not parse the file as passive configuration data; it executes every statement in that file in the current shell process.The file path defaults to
~/.habitica, but it can also be selected through theHABITICA_CONFIGenvironment variable. Consequently, anyone able to modify the default credential file or influence both the environment and referenced file can cause arbitrary shell commands to run when any Habitica command invokesload_creds.The malicious content does not need to resemble a credential assignment. It can contain command substitutions, shell functions, redirections, pipelines, or direct command invocations. Execution occurs before the requested Habitica API operation and inherits the script's user privileges and environment, including credentials subsequently loaded by the file.
Attack Path
- An attacker gains write access to
~/.habitica, or causesHABITICA_CONFIGto reference a file under attacker control. - The attacker inserts shell commands into that file, for example:
bash HABITICA_USER_ID="expected-user" HABITICA_API_TOKEN="expected-token" arbitrary_command - The user or AI Agent invokes any command through
scripts/habitica.sh. load_credscallssource "$CONFIG_FILE".- Bash executes
arbitrary_commandwith the privileges of the user running the skill. - The injected command can access local files and environment variables, steal credentials, alter ...[truncated 1003 chars]
- An attacker gains write access to
- Remediation
View remediation
Remediation Suggestions
- Do not use
source,., orevalto read credential files. - Parse only an explicit allowlist of supported keys, such as
HABITICA_USER_IDandHABITICA_API_TOKEN. - Reject unknown keys, shell metacharacters, command substitutions, malformed lines, and duplicate assignments.
- Verify that the configuration is a regular file owned by the current user and is not a symbolic link.
- Require restrictive permissions, preferably mode
0600, and fail securely when ownership or permissions are unsafe. - Validate values according to Habitica's expected credential formats before using them.
- If
HABITICA_CONFIGremains supported, treat it as untrusted input and apply the same ownership, type, and permission checks to the selected path. - Prefer a dedicated secret store or environment variables supplied through a trusted execution environment.
A safe implementation should read values as data rather than shell syntax, for example by using a strict parser:
bash load_creds() { local config_file="${HABITICA_CONFIG:-$HOME/.habitica}" if [[ -f "$config_file" ]]; then while IFS='=' read -r key value; do [[ -z "$key" || "$key" == \#* ]] && continue value="${value%$'\r'}" if [[ "$value" == \"*\" && "$value" == *\" ]]; then value="${value:1:${#value}-2}" fi case "$key" in HABITICA_USER_ID) HABITICA_USER_ID="$value" ;; HABITICA_API_TOKEN) HABITICA_API_TOKEN="$value" ;; *) echo "Error: Unsupported configuration key: $key" >&2 exit 1 ;; esac done < "$config_file" fi if [[ -z "${HABITICA_USER_ID:-}" || -z "${HABITICA_API_TOKEN:-}" ]]; then echo "Error: Habitica credentials not found." >&2 exit 1 fi } ...[truncated 102 chars]- Do not use
