Back to skill

Security audit

file-browser

Security checks for vulnerabilities and agentic risk

Overview

This read-only workspace file browser has a real containment flaw that can expose files outside the intended workspace through symlinks.

Review before installing. The skill is not trying to write, persist, or fetch remote code, but it should not be trusted as a strict workspace-only browser until paths are canonicalized and JSON output is produced with a real encoder.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

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. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/list_files.sh:16
Finding
Unescaped File Names and Contents Produce Unsafe JSON Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/list_files.sh:16-18`; `scripts/read_file.sh:18-19` **Vulnerability Type**: Improper encoding of untrusted data in JSON output **Risk Level**: Medium ### Vulnerable Code `scripts/list_files.sh:16-18`: ```bash FILES=$(ls -1 "$FULL_PATH") echo "{\"success\": true, \"data\": [\"${FILES//$'\n'/'", "'}\"]}" ``` `scripts/read_file.sh:18-19`: ```bash CONTENT=$(head -c 10240 "$FULL_PATH" | tr -d '\0') echo "{\"success\": true, \"data\": \"$CONTENT\"}" ``` ### Technical Analysis Both scripts construct JSON by directly interpolating untrusted file names or file contents into JSON syntax. They do not escape double quotes, backslashes, line breaks, tabs, carriage returns, or other JSON control characters. In `list_files.sh`, newline-delimited output from `ls` is transformed into apparent JSON array separators. Unix file names may contain newlines, quotes, and backslashes, so this transformation cannot reliably distinguish separate entries from characters within a file name. In `read_file.sh`, arbitrary text is inserted directly into a quoted JSON string. A file containing quotation marks, backslashes, or literal line breaks causes malformed JSON and may create attacker-shaped fields if a downstream consumer uses permissive parsing or string-based processing. The script also does not implement the documented binary-file rejection. It only removes NUL bytes, potentially changing binary or mixed content before inserting it into the response. ### Attack Path 1. An attacker places a file with specially crafted content in the workspace or creates a file name containing quotes, backslashes, or newline characters. 2. The attacker requests that the Skill read the file or list its containing directory. 3. The relevant script interpolates the attacker-controlled value directly into its JSON response. 4. The response becomes malformed or contains attacker-shaped JSON syntax. 5. A downstream Agent, wrapper, log pr ...[truncated 998 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use a dedicated JSON encoder rather than constructing JSON with shell interpolation. For file contents, `jq` can safely encode arbitrary text: ```bash CONTENT=$(head -c 10240 -- "$FULL_PATH" | tr -d '\0') jq -n --arg data "$CONTENT" '{success: true, data: $data}' ``` For directory listings, avoid parsing `ls`. Read entries using NUL delimiters and pass each value through a JSON encoder. For example, use `find` with `-print0` and build the array with a language or utility that correctly handles arbitrary file names. Additional hardening should include: 1. Define whether non-UTF-8 and binary files are supported. 2. If binary files are prohibited, detect and reject them instead of deleting NUL bytes. 3. If binary data must be returned, encode it with Base64 and identify the encoding explicitly. 4. Ensure error responses are generated through the same JSON library. 5. Add tests for quotes, backslashes, tabs, carriage returns, newlines, Unicode, empty files, long files, and non-text content. 6. Validate generated output with a strict JSON parser in automated tests. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.