T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/es_search.sh:40
- Finding
- Shell Command Injection Through eval in the Bash Wrapper<![CDATA[ ## Vulnerability Details **File Location**: `scripts/es_search.sh`, lines 40-72 and 143-167 **Vulnerability Type**: OS command injection caused by unsafe command reconstruction and `eval` **Risk Level**: High ### Vulnerable Code ```bash build_cmd() { local cmd=("$ES_PATH") # Add options if [[ -n "$ES_PATH_ARG" ]]; then cmd+=("-p" "$ES_PATH_ARG") fi if [[ "$ES_REGEX" == "true" ]]; then cmd+=("-regex") fi if [[ "$ES_CASE" == "true" ]]; then cmd+=("-case") else cmd+=("-nocase") fi if [[ "$ES_WHOLE_WORD" == "true" ]]; then cmd+=("-wholeword") fi if [[ "$ES_MATCH_PATH" == "true" ]]; then cmd+=("-matchpath") fi if [[ -n "$ES_SORT" ]]; then cmd+=("-sort" "$ES_SORT") fi if [[ "$ES_SORT_DESC" == "true" ]]; then cmd+=("-sort-descending") fi if [[ "$ES_DETAILS" == "true" ]]; then cmd+=("-details") fi # Add query cmd+=("$ES_QUERY") echo "${cmd[@]}" } ``` ```bash # Build command local cmd cmd=$(build_cmd) # Execute search info "Searching for: $ES_QUERY" if [[ -n "$ES_PATH_ARG" ]]; then info "Path: $ES_PATH_ARG" fi # Run command if [[ "$ES_JSON" == "true" ]]; then # Output as JSON local output output=$(eval "$cmd" 2>&1) echo "$output" | jq -R 'split("\n") | map(select(length > 0)) | map({path: .})' 2>/dev/null || echo "$output" else # Output as text eval "$cmd" fi ``` ### Technical Analysis The script initially constructs the command as a Bash array, which would normally preserve argument boundaries. However, `build_cmd` serializes that array into a plain string using `echo`, and the caller subsequently executes the string with `eval`. Values controlled by the caller—including the search query, path, sort field, and `ES_PATH` environment variable—therefore undergo a second round of shell parsing. Shell separators, substitutions, redirections, and other metacharact ...[truncated 1445 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Remove all use of `eval`. - Construct and execute the command in the same function while retaining it as a Bash array: ```bash cmd=("$ES_PATH") if [[ -n "$ES_PATH_ARG" ]]; then cmd+=("-p" "$ES_PATH_ARG") fi # Add other options as separate array elements. cmd+=("$ES_QUERY") if [[ "$ES_JSON" == "true" ]]; then output=$("${cmd[@]}" 2>&1) else "${cmd[@]}" fi ``` - Do not return arrays through `echo` and command substitution. - Resolve `ES_PATH` to an approved executable and reject unexpected executable paths where the environment is not fully trusted. - Validate options that have a finite set of permitted values, such as sort fields. - Add regression tests containing spaces, semicolons, command substitutions, redirections, and quotes to verify that every supplied value remains a single literal argument. ]]>
