T09 · Insecure Skill Coding Practices
Warning
- Location
SKILL.md:73- Finding
Predictable Temporary Files Allow Symlink-Based File Overwrite
- Content
View full analysis
"$OUTPUT_FILE" agents=$(pilotctl --json trust 2>/dev/null | jq -r '.data.trusted[].hostname') for agent in $agents; do ping_result=$(pilotctl --json ping "$agent" 2>/dev/null) rtt_ms=$(echo "$ping_result" | jq -r '.data.results[0].rtt_ms // null') agent_data=$(jq -n --arg hostname "$agent" --arg rtt "$rtt_ms" \ '{hostname: $hostname, rtt_ms: ($rtt | tonumber), status: "online"}') jq --argjson agent "$agent_data" '.agents += [$agent]' "$OUTPUT_FILE" > "${OUTPUT_FILE}.tmp" mv "${OUTPUT_FILE}.tmp" "$OUTPUT_FILE" done ``` ### Technical Analysis The workflow creates files directly in the shared `/tmp` directory using names derived from the current timestamp. Both the main output path and its `.tmp` companion are predictable: - `/tmp/fleet-metrics-YYYYMMDD-HHMMSS.json` - `/tmp/fleet-metrics-YYYYMMDD-HHMMSS.json.tmp` The files are not created atomically or exclusively, and the workflow does not verify that either path is a regular file owned by the current user. Shell output redirection follows symbolic links. Consequently, if another local user creates a symbolic link at the predicted output path before execution, the initial `echo ... > "$OUTPUT_FILE"` operation truncates and writes to the symlink target. The same issue applies to `"${OUTPUT_FILE}.tmp"`. The redirection used for the `jq` result follows a pre-existing symlink and can overwrite its target before the subsequent `mv` operation occurs. Successful exploitation requires the attacker to share the host, predict or race the second-resolution filename, and select a target writable by the account running the workflow. ### Attack Path 1. A local ...[truncated 1330 chars]- Remediation
View remediation
"$OUTPUT_FILE" ``` For each update, create another unpredictable file inside the private directory and atomically replace the output only after `jq` succeeds: ```bash NEXT_FILE=$(mktemp "$TMP_DIR/fleet-metrics.next.XXXXXX") if jq --argjson agent "$agent_data" \ '.agents += [$agent]' "$OUTPUT_FILE" > "$NEXT_FILE"; then mv -- "$NEXT_FILE" "$OUTPUT_FILE" else rm -f -- "$NEXT_FILE" exit 1 fi ``` Additional hardening measures include: - Do not create predictable files directly in a shared temporary directory. - Set `umask 077` so generated metrics are not exposed to other local users. - Use `mktemp` rather than timestamp-only names. - Quote every path and use `--` before path operands where supported. - Enable `set -euo pipefail` and replace output only after successful JSON processing. - If the finished report must persist, copy it from the private directory to a trusted destination using an explicitly configured path and appropriate ownership checks. ]]>
