T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/daily_pipeline.sh:25
- Finding
- Unvalidated radar type permits path traversal and execution of unintended Python scripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/daily_pipeline.sh`, lines 25–56 **Vulnerability Type**: Path traversal, unsafe executable path construction, and Python source injection **Risk Level**: High ### Vulnerable Code ```bash RADAR_TYPE="${1:?用法: $0 <radar_type> <name> <category> <emoji> <source>}" RADAR_NAME="${2:?}" CATEGORY="${3:?}" EMOJI="${4:?}" SOURCE="${5:?}" TODAY="$(date '+%Y-%m-%d')" TMP="/tmp/radar_${RADAR_TYPE}.md" # ── Step 1:生成日报 ────────────────────────────────── RADAR_MAIN="$SKILL_DIR/../${RADAR_TYPE}/main.py" if [[ -f "$RADAR_MAIN" ]]; then python3 "$RADAR_MAIN" > "$TMP" else echo "⚠️ 未找到 $RADAR_MAIN,跳过生成步骤" exit 0 fi # ── Step 2:写入 Obsidian inbox ────────────────────── # 模板:用 capture.py 写入(结构化版本) # 如 radar 提供了独立格式脚本,优先用其写入结构化 Obsidian 文件 FORMAT_SCRIPT="$SKILL_DIR/../${RADAR_TYPE}/format_push.py" if [[ -f "$FORMAT_SCRIPT" ]]; then python3 "$FORMAT_SCRIPT" \ "$RADAR_TYPE" "$RADAR_NAME" "$SOURCE" "$CATEGORY" "$EMOJI" "$TODAY" \ > /dev/null 2>&1 OBSIDIAN_PATH="$(python3 -c " import sys for line in open('$TMP'): if line.startswith('OBSIDIAN|'): print(line.split('|',1)[1].strip()) ")" ``` ### Technical Analysis `RADAR_TYPE` is taken directly from the first command-line argument without an allowlist, canonicalization, or containment check. It is then used to construct the paths of `main.py` and `format_push.py`, both of which are executed by the pipeline. Because values such as `../` are not rejected, the resolved script path can escape the expected sibling skill directory. Shell quoting prevents ordinary shell metacharacter expansion at these execution sites, but it does not prevent filesystem traversal. The same value also controls `TMP`, which is embedded directly inside Python source passed to `python3 -c`. A value containing a single quote and valid Python syntax could modify the generated Python program. Reaching that code requires the earlier generated paths to satisfy the file che ...[truncated 1502 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict `RADAR_TYPE` to a narrow identifier format before using it: ```bash if [[ ! "$RADAR_TYPE" =~ ^[A-Za-z0-9_-]+$ ]]; then echo "Invalid radar type" >&2 exit 1 fi ``` 2. Define a trusted skill root and canonicalize every executable path with `realpath`. 3. Verify that each resolved path is a descendant of the trusted skill root before execution. 4. Consider using an explicit allowlist mapping radar identifiers to approved script paths rather than constructing executable paths from user input. 5. Never interpolate shell-controlled values into Python source. Pass the temporary path as an argument: ```bash python3 - "$TMP" <<'PY' import sys with open(sys.argv[1], encoding="utf-8") as file: for line in file: if line.startswith("OBSIDIAN|"): print(line.split("|", 1)[1].strip()) PY ``` 6. Run scheduled pipelines under a dedicated least-privileged account with access only to the required skill directories and vault paths. ]]>
