T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/read_file.sh:4
- Finding
- Workspace Boundary Bypass Through Symbolic Links<![CDATA[ ## Vulnerability Details **File Location**: `scripts/list_files.sh:4-16`; `scripts/read_file.sh:4-18` **Vulnerability Type**: Path containment bypass through symbolic-link traversal **Risk Level**: High ### Vulnerable Code `scripts/list_files.sh:4-16`: ```bash REL_PATH="$1" FULL_PATH="$WORKSPACE/$REL_PATH" # Sanitize: No .. or absolute if [[ "$REL_PATH" == *'..'* || "$REL_PATH" == '/'* ]]; then echo '{"success": false, "error": "Invalid path"}' exit 1 fi if [ ! -d "$FULL_PATH" ]; then echo '{"success": false, "error": "Not a directory"}' exit 1 fi FILES=$(ls -1 "$FULL_PATH") ``` `scripts/read_file.sh:4-18`: ```bash REL_PATH="$1" FULL_PATH="$WORKSPACE/$REL_PATH" # Sanitize if [[ "$REL_PATH" == *'..'* || "$REL_PATH" == '/'* ]]; then echo '{"success": false, "error": "Invalid path"}' exit 1 fi if [ ! -f "$FULL_PATH" ] || [ ! -r "$FULL_PATH" ]; then echo '{"success": false, "error": "File not found or unreadable"}' exit 1 fi # Limit size (e.g., head -c 10240) CONTENT=$(head -c 10240 "$FULL_PATH" | tr -d '\0') ``` ### Technical Analysis The scripts attempt to enforce workspace containment by rejecting absolute paths and any input containing `..`. This is insufficient because they concatenate the untrusted relative path with the workspace path without resolving the resulting path to its canonical location. The `-d`, `-f`, and `-r` tests follow symbolic links. The subsequent `ls` and `head` commands also follow symbolic links. Consequently, a symbolic link located inside `/home/alfred/.openclaw/workspace` can resolve to a file or directory outside that workspace while still passing the string-based validation. This behavior contradicts the workspace restriction declared in `SKILL.md`. ### Attack Path 1. An attacker creates a symbolic link in the workspace, or identifies an existing one. For example: ```bash ln -s /etc /home/alfred/.openclaw/workspace/external ``` 2. The attacker asks the Skill to list `external`. 3. `list_files.sh` ...[truncated 1156 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Canonicalize the workspace and requested target before any access, and verify containment using path-component-aware comparison: ```bash WORKSPACE_REAL=$(realpath -- "$WORKSPACE") || exit 1 TARGET_REAL=$(realpath -- "$WORKSPACE/$REL_PATH") || { printf '%s\n' '{"success":false,"error":"Invalid path"}' exit 1 } case "$TARGET_REAL" in "$WORKSPACE_REAL"|"$WORKSPACE_REAL"/*) ;; *) printf '%s\n' '{"success":false,"error":"Invalid path"}' exit 1 ;; esac ``` Additional hardening should include: 1. Explicitly reject symbolic links if they are not required by the Skill. 2. Check every path component with a mechanism that does not follow symlinks where feasible. 3. Perform the file operation on a verified descriptor to reduce time-of-check/time-of-use race conditions. 4. Run the scripts under a minimally privileged account that cannot read unrelated sensitive files. 5. Add tests covering symlinks to external files, symlinks to external directories, chained symlinks, nonexistent targets, and race-condition attempts. ]]>
