T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/speech_to_text.sh:145
- Finding
- Zhipu API Key Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/speech_to_text.sh`, lines 145–164 **Vulnerability Type**: Credential exposure through process arguments **Risk Level**: Medium **Vulnerable Code**: ```bash # Build curl command arguments CURL_ARGS=() CURL_ARGS+=(-H "Authorization: Bearer $ZHIPU_API_KEY") CURL_ARGS+=(-F "file=@$AUDIO_FILE") CURL_ARGS+=(-F "model=glm-asr-2512") if [ -n "$PROMPT" ]; then CURL_ARGS+=(-F "prompt=$PROMPT") fi if [ -n "$HOTWORDS" ]; then # Convert comma-separated to array format for curl IFS=',' read -ra HW_ARRAY <<< "$HOTWORDS" for word in "${HW_ARRAY[@]}"; do word=$(echo "$word" | xargs) CURL_ARGS+=(-F "hotwords[]=$word") done fi RESPONSE=$(curl -s -X POST "$API_ENDPOINT" "${CURL_ARGS[@]}") ``` ### Technical Analysis The script places `ZHIPU_API_KEY` directly in a `curl` header passed as a command-line argument. Shell arrays prevent word splitting and command injection here, but they do not conceal the resulting arguments from operating-system process inspection. While `curl` is running, the expanded `Authorization: Bearer ...` argument may be accessible through process-monitoring interfaces such as `/proc/<pid>/cmdline`, `ps`, or auditing and monitoring software. Exploitation requires local process-inspection access, generally from the same account or a sufficiently privileged account, depending on operating-system process-isolation settings. ### Attack Path 1. A victim runs `scripts/speech_to_text.sh` with a valid `ZHIPU_API_KEY`. 2. The script launches `curl` and embeds the bearer token in its argument vector. 3. A local attacker or monitoring process observes newly launched `curl` processes. 4. The attacker reads the process arguments while the request is active and extracts the Authorization header. 5. The attacker reuses the recovered token when sending requests to Zhipu AI. The observation window may be ...[truncated 577 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Avoid placing secrets directly in process arguments. 1. Create a temporary curl configuration file under a restrictive `umask`, such as `umask 077`. 2. Write the Authorization header to that file and ensure its permissions are `0600`. 3. invoke `curl` with only the configuration file path visible in its arguments. 4. Register an `EXIT`, `INT`, and `TERM` cleanup handler immediately after creating the file. 5. Securely revoke and rotate any API key suspected of prior exposure. 6. Avoid printing the key or temporary configuration contents in debug output. Example hardening pattern: ```bash umask 077 CURL_CONFIG=$(mktemp) cleanup() { [ -n "${TEMP_AUDIO:-}" ] && [ -f "$TEMP_AUDIO" ] && rm -f -- "$TEMP_AUDIO" [ -n "${CURL_CONFIG:-}" ] && [ -f "$CURL_CONFIG" ] && rm -f -- "$CURL_CONFIG" } trap cleanup EXIT INT TERM printf 'header = "Authorization: Bearer %s"\n' "$ZHIPU_API_KEY" > "$CURL_CONFIG" RESPONSE=$(curl --silent --show-error \ --config "$CURL_CONFIG" \ --request POST \ "$API_ENDPOINT" \ --form "file=@$AUDIO_FILE" \ --form "model=glm-asr-2512") ``` The implementation should also preserve the existing prompt and hotword form fields without placing the API key back into the argument vector. ]]>
