T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/send_voice_feishu.sh:51
- Finding
- Arbitrary Python Code Execution Through an Untrusted Audio Filename## Vulnerability Details **File Location**: `scripts/send_voice_feishu.sh`, lines 51–61 **Vulnerability Type**: Python source-code injection **Risk Level**: High **Vulnerable Code**: ```bash # 计算音频时长(毫秒),用于后续发送消息时传入 duration 字段 DURATION_MS=$(python3 -c " import wave, os try: with wave.open('$WAV_FILE') as f: frames = f.getnframes() rate = f.getframerate() print(int(frames / rate * 1000)) except Exception as e: print(0) ") ``` ### Technical Analysis `WAV_FILE` originates from the first command-line argument and is interpolated directly into source code passed to `python3 -c`. Shell quoting around the outer command does not make this safe because the expanded value becomes part of the Python program. A filename containing a single quote, Python delimiters, and additional statements can terminate the argument to `wave.open`, alter the generated Python program, and execute attacker-selected Python code. The preceding file-existence check only verifies that the supplied pathname exists; it does not validate or neutralize characters that are meaningful in Python source. The vulnerable duration calculation occurs after Feishu credentials have been loaded from `FEISHU_APP_ID` and `FEISHU_APP_SECRET`. Injected code therefore executes in a process environment that can access those credentials. ### Attack Path 1. An attacker creates or causes the user to receive a file whose pathname contains Python source-code metacharacters. 2. The attacker persuades the user or an automated workflow to invoke `send_voice_feishu.sh` with that pathname as the first argument. 3. The pathname passes the `[ -f "$WAV_FILE" ]` existence check. 4. The shell expands `$WAV_FILE` inside the program supplied to `python3 -c`. 5. The embedded quote terminates the intended Python string, and attacker-controlled statements become executable Python source. 6. Python executes those statements with the permissi ...[truncated 653 chars]
- Remediation
- ## Remediation Suggestions Never interpolate a pathname into generated Python source. Pass it as a positional argument and read it through `sys.argv`: ```bash DURATION_MS=$(python3 -c ' import sys import wave try: with wave.open(sys.argv[1]) as audio: frames = audio.getnframes() rate = audio.getframerate() print(int(frames / rate * 1000)) except Exception: print(0) ' "$WAV_FILE") ``` Additional hardening should include: - Use `set -euo pipefail` and reference optional environment variables as `${FEISHU_APP_ID:-}` and `${FEISHU_APP_SECRET:-}`. - Treat all command-line pathnames as untrusted and pass them only as quoted data arguments. - Avoid constructing source code, JSON, or shell commands through string interpolation. - Add regression tests using filenames containing quotes, spaces, newlines, leading hyphens, and shell or Python metacharacters. - Run the Skill under an unprivileged account and provide Feishu credentials only for the duration of the send operation.
