T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/scan.sh:37
- Finding
- Persistent Arbitrary Command Execution Through Sourced Environment Snapshot<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:57-65`; `scripts/scan.sh:37-40` **Vulnerability Type**: Executable configuration injection **Risk Level**: High ### Vulnerable Code ```bash # SKILL.md:57-65 cat > ~/.okx/earn-hunter/env.snapshot << SNAP # auto-generated by earn-hunter activation — $(date -Iseconds) OKX_BIN=$(command -v okx) NODE_BIN=$(command -v node) JQ_BIN=$(command -v jq) ACTIVATION_PATH=$PATH SNAP ``` ```bash # scripts/scan.sh:37-40 _EH_SNAPSHOT="${EH_STATE_DIR:-$HOME/.okx/earn-hunter}/env.snapshot" # shellcheck disable=SC1090 [[ -f "$_EH_SNAPSHOT" ]] && source "$_EH_SNAPSHOT" ``` ### Technical Analysis The activation procedure generates `env.snapshot` by interpolating executable paths and the current `PATH` without shell escaping. The scanner subsequently loads this file using `source`, which treats its contents as shell code rather than inert configuration data. If an executable path or `PATH` entry contains shell metacharacters, command substitution, or statement delimiters, those characters are written into the snapshot and interpreted when the scheduled scanner sources it. The problem is especially significant because the scanner can be registered in OS crontab or a macOS LaunchAgent, causing injected commands to execute repeatedly across sessions. The file also resides in a user-controlled state directory without an explicit ownership, regular-file, or restrictive-permission check before it is sourced. ### Attack Path 1. An attacker who can influence the activation environment places a maliciously named directory or executable earlier in `PATH`, or modifies `~/.okx/earn-hunter/env.snapshot` after activation. 2. `command -v` or `$PATH` produces text containing shell syntax, such as command substitution or an additional command. 3. Activation writes that text to `env.snapshot` without escaping it. 4. The Skill installs or invokes the recurring scanner. 5. `scan.sh` executes `source "$_EH_SNAPSHOT"`. 6. Bash parses t ...[truncated 553 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not use `source` to read generated configuration. 2. Store resolved paths in a non-executable format such as JSON: ```bash jq -n \ --arg okx "$(command -v okx)" \ --arg node "$(command -v node)" \ --arg jq_bin "$(command -v jq)" \ '{okx_bin:$okx,node_bin:$node,jq_bin:$jq_bin}' \ > ~/.okx/earn-hunter/env.snapshot.json chmod 600 ~/.okx/earn-hunter/env.snapshot.json ``` 3. Read individual values using the already resolved trusted `jq` binary, without evaluating their contents. 4. If shell assignments must be retained, serialize every value with `printf '%q'`; replacing `source` remains preferable. 5. Create `~/.okx/earn-hunter` with mode `0700` and snapshot/configuration files with mode `0600`. 6. Before reading the snapshot, verify that it is a regular file, is owned by the current user, is not a symbolic link, and is not writable by group or other users. 7. Validate resolved paths against an allowlist of expected absolute-path characters and verify the ownership and executable type of each selected binary. ]]>
