T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/anythingllm.sh:21
- Finding
- Arbitrary Command Execution Through Shell eval<![CDATA[ ## Vulnerability Details **File Location**: `scripts/anythingllm.sh`, lines 21–35 and 79–94 **Vulnerability Type**: Shell command injection caused by unsafe command-string construction and `eval` **Risk Level**: Critical ### Vulnerable Code ```bash api_call() { local method="$1" local endpoint="$2" local data="$3" local curl_cmd="curl -s -w '\n%{http_code}' -X ${method} \ -H 'Authorization: Bearer ${ANYTHINGLLM_API_KEY}' \ -H 'Content-Type: application/json' \ '${ANYTHINGLLM_URL}/api${endpoint}'" if [ -n "$data" ]; then curl_cmd="${curl_cmd} -d '${data}'" fi local response=$(eval "$curl_cmd") local http_code=$(echo "$response" | tail -n1) local body=$(echo "$response" | sed '$d') ``` The attacker-controlled data can originate from the raw-text upload function: ```bash upload_text() { local text="$1" local title="$2" local workspace="${3:-$DEFAULT_WORKSPACE}" local payload=$(cat <<EOF { "textContent": "$(echo "$text" | sed 's/"/\\"/g' | tr '\n' ' ')", "metadata": { "title": "${title}" }, "addToWorkspaces": "${workspace}" } EOF ) api_call "POST" "/v1/document/raw-text" "$payload" } ``` ### Technical Analysis `api_call` constructs an entire shell command as a string and then reparses it with `eval`. The JSON body is inserted into a single-quoted `-d` argument: ```bash curl_cmd="${curl_cmd} -d '${data}'" ``` The `upload_text` function only escapes double quotation marks in `text`; it does not escape shell-significant single quotation marks. The `title` and `workspace` values are not safely JSON-encoded or shell-escaped either. Consequently, an apostrophe in supplied content can terminate the intended single-quoted argument. Subsequent shell syntax is then interpreted by `eval`. Environment-controlled values such as `ANYTHINGLLM_URL` and `ANYTHINGLLM_API_KEY` are also interpolated into the evaluated command string ...[truncated 1794 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `eval` and never build a shell command as a string. 2. Call `curl` directly with individually quoted arguments or a Bash array: ```bash local curl_args=( -s -w $'\n%{http_code}' -X "$method" -H "Authorization: Bearer $ANYTHINGLLM_API_KEY" -H "Content-Type: application/json" ) if [[ -n "$data" ]]; then curl_args+=(-d "$data") fi response="$(curl "${curl_args[@]}" "${ANYTHINGLLM_URL}/api${endpoint}")" ``` 3. Generate JSON with a proper serializer such as `jq`, rather than escaping selected characters with `sed`: ```bash payload="$(jq -n \ --arg text "$text" \ --arg title "$title" \ --arg workspace "$workspace" \ '{textContent: $text, metadata: {title: $title}, addToWorkspaces: $workspace}')" ``` 4. Validate the API URL and restrict it to expected schemes and hosts. 5. Validate workspace identifiers against the format accepted by AnythingLLM. 6. Add regression tests containing apostrophes, quotation marks, command substitutions, semicolons, newlines, and shell metacharacters. 7. Run the skill under a least-privileged account to reduce impact if another command-injection defect is introduced. ]]>
