T09 · Insecure Skill Coding Practices
- Location
scripts/poll-template.sh:90- Finding
Arbitrary Shell Command Execution Through Configurable eval Expressions
- Content
View full analysis
&1) || { log "Command failed: $OUTPUT" save_progress "$POLL_COUNT" "command_failed" sleep "$POLL_INTERVAL" continue } log "Output: ${OUTPUT:0:200}" PARSED=$(eval "$PARSE_OUTPUT" <<< "$OUTPUT" 2>/dev/null) || PARSED="parse_error" ``` The evaluated variables are configured earlier in the same file: ```bash POLL_COMMAND='echo "Replace this with the actual status check command"' PARSE_OUTPUT='jq -r ".status" <<< "$OUTPUT"' ``` ### Technical Analysis The script uses `eval` to interpret both `POLL_COMMAND` and `PARSE_OUTPUT` as shell source code. Unlike executing a fixed command with a separately quoted argument array, `eval` performs another complete round of shell parsing. Shell metacharacters, command substitutions, redirections, pipelines, and additional commands contained in either variable are therefore executed. The template instructs users or agents to customize these strings for each polling task. If a job identifier, artifact name, path, status expression, or other untrusted value is concatenated into either configuration string, quoting at the original assignment site may not remain effective during the second parsing pass. The polling script is intended to run unattended with the permissions of the invoking agent or user. Consequently, injected commands execute under that same account and are not restricted to the polling task directory. ### Attack Path 1. An attacker controls or influences a value used to construct `POLL_COMMAND` or `PARSE_OUTPUT`, such as a job ID, artifact ID, filename, API-provided handle, or user-supplied parsing expression. 2. The generated configuration embeds that value into one of the shell command strings. 3. The ...[truncated 1096 chars]- Remediation
View remediation
&1); then save_progress "$POLL_COUNT" "command_failed" error_exit "Polling command failed" fi ``` 3. Validate identifiers before using them. For example, require job IDs to match a narrowly defined format: ```bash [[ "$JOB_ID" =~ ^[A-Za-z0-9._-]+$ ]] || error_exit "Invalid job identifier" ``` 4. Replace configurable parsing source code with fixed parser functions. Select a parser using a strict enumerated value rather than an executable expression: ```bash case "$PARSER_TYPE" in json-status) PARSED=$(jq -r '.status // empty' <<< "$OUTPUT") ;; plain-status) PARSED=$(awk -F ': ' '$1 == "status" {print $2; exit}' <<< "$OUTPUT") ;; *) error_exit "Unsupported parser type" ;; esac ``` 5. Keep user-controlled values exclusively in data variables and pass them as quoted arguments. Do not interpolate them into shell programs. 6. If arbitrary commands are an unavoidable feature, require explicit trusted configuration, reject shell metacharacters where possible, run the command with reduced privileges, and document that configuration values must never contain untrusted data. ]]>
