T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/run_cancel.sh:47
- Finding
- Path Traversal Allows Cancellation of Unintended tmux Sessions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_cancel.sh`, lines 47-49, 61-80, and 84-95 **Vulnerability Type**: Path traversal and insufficient authorization boundary validation **Risk Level**: High ### Vulnerable Code ```bash if [[ "$RUN_ID" == */* ]]; then CANDIDATE="$RESULTS_BASE/$RUN_ID" [[ -d "$CANDIDATE" ]] && TARGET_DIR="$CANDIDATE" else mapfile -t MATCHES < <(find "$RESULTS_BASE" -mindepth 2 -maxdepth 2 -type d -name "$RUN_ID" 2>/dev/null | sort) if [[ ${#MATCHES[@]} -eq 1 ]]; then TARGET_DIR="${MATCHES[0]}" elif [[ ${#MATCHES[@]} -gt 1 ]]; then echo "Error: run-id is ambiguous. Use <project>/<run-id>. Matches:" >&2 printf '%s\n' "${MATCHES[@]}" >&2 exit 2 fi fi if [[ -z "$TARGET_DIR" || ! -d "$TARGET_DIR" ]]; then echo "Error: run-id not found: $RUN_ID" >&2 exit 2 fi META="$TARGET_DIR/task-meta.json" if [[ ! -f "$META" ]]; then echo "Error: task-meta.json not found in $TARGET_DIR" >&2 exit 2 fi TMUX_SESSION=$(jq -r '.tmux_session // ""' "$META") TMUX_SOCKET_NAME=$(jq -r '.tmux_socket_name // ""' "$META") if [[ -z "$TMUX_SESSION" || -z "$TMUX_SOCKET_NAME" ]]; then echo "Error: tmux metadata missing in task-meta.json" >&2 exit 2 fi SOCKET_PATH="$SOCKET_DIR/$TMUX_SOCKET_NAME" TARGET="${TMUX_SESSION}:0.0" set +e tmux -S "$SOCKET_PATH" send-keys -t "$TARGET" -l -- "/ralph-loop:cancel-ralph" tmux -S "$SOCKET_PATH" send-keys -t "$TARGET" Enter sleep 1 tmux -S "$SOCKET_PATH" send-keys -t "$TARGET" -l -- "/exit" tmux -S "$SOCKET_PATH" send-keys -t "$TARGET" Enter sleep 2 tmux -S "$SOCKET_PATH" kill-session -t "$TMUX_SESSION" set -e jq --arg ts "$(date -Iseconds)" '. + {status:"cancelled", completed_at:$ts, exit_code:130}' "$META" > "$META.tmp" && mv "$META.tmp" "$META" ``` ### Technical Analysis When the supplied run identifier contains a slash, it is directly appended to `RESULTS_BASE`. The resulting path is only checked with `-d`; it is not canonicalized, and the script does not verify that ...[truncated 2126 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Validate both project and run identifiers against a conservative allowlist, such as alphanumeric characters, underscores, periods, and hyphens. 2. Explicitly reject empty components and the special path components `.` and `..`. 3. Canonicalize `RESULTS_BASE` and the candidate directory with `realpath`. 4. Require the canonical candidate path to be a strict descendant of the canonical results root before reading metadata: ```bash BASE_REAL="$(realpath -- "$RESULTS_BASE")" CANDIDATE_REAL="$(realpath -- "$CANDIDATE")" case "$CANDIDATE_REAL" in "$BASE_REAL"/*) ;; *) echo "Error: run directory escapes results base" >&2 exit 2 ;; esac ``` 5. Enforce the documented `<project>/<run-id>` structure rather than accepting arbitrary slash-containing paths. 6. Validate `tmux_socket_name` as a simple socket filename and reject slashes or traversal components. 7. Verify that the resolved socket and session are associated with the selected run, rather than trusting metadata alone. 8. Apply equivalent containment checks after path resolution to mitigate symbolic-link escapes. ]]>
