T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/write-file.sh:51
- Finding
- Workspace Symlinks Permit Writes Outside the Configured Workspace## Vulnerability Details **File Location**: `scripts/write-file.sh:51-65` **Vulnerability Type**: Symlink-following arbitrary file overwrite **Risk Level**: Medium ### Vulnerable Code ```bash TARGET="$WORKSPACE/$FILENAME" # --- Check overwrite --- if [ -f "$TARGET" ] && [ "$FORCE" != "true" ]; then echo "ERROR: $FILENAME already exists. Use --force to overwrite." exit 1 fi # --- Validate content --- validate_shell_safety "content" "$CONTENT" check_prompt_injection_tiered "$CONTENT" "$FILENAME" "content" # --- Write file --- mkdir -p "$WORKSPACE" printf '%s\n' "$CONTENT" > "$TARGET" ``` The same filesystem weakness affects fixed-target writes in `scripts/log-training.sh:136-187`, scaffold creation in `scripts/scaffold.sh:12-13`, and predictable rate-limit files in `scripts/lib/security.sh:17-44`. ### Technical Analysis The scripts prevent lexical path traversal by restricting filenames, but they do not reject symbolic links or verify that the resolved destination remains under `OPENCLAW_WORKSPACE`. Shell redirection follows symbolic links. In `write-file.sh`, an existing symlink to a regular file is protected unless `--force` is supplied, after which the external target is overwritten. A dangling symlink is not recognized by `[ -f "$TARGET" ]` and is followed during creation. Other scripts append to or create fixed filenames without equivalent overwrite protection. This exceeds the minimum privileges needed for workspace management because writes intended to be confined to the workspace can affect arbitrary user-writable locations. ### Attack Path 1. An attacker gains the ability to prepare, import, or modify a workspace used by the operator. 2. The attacker creates a symlink at a recognized destination, such as `SOUL.md`, `AGENTS.md`, or `MEMORY.md`, pointing to another user-writable file outside the workspace. 3. The operator invokes setup, forced writing, scaffolding, or training logging. ...[truncated 650 chars]
- Remediation
- ## Remediation Suggestions - Reject symbolic-link destinations using `[ -L "$TARGET" ]` before every create, append, move, or overwrite operation. - Resolve the workspace and destination parent with `realpath` or an equivalent portable implementation, then verify that the resolved destination remains beneath the canonical workspace path. - Open files with exclusive-creation or no-follow semantics where supported. - Create replacement files with `mktemp` inside a trusted workspace directory, set restrictive permissions, and atomically rename them only after revalidating the destination. - Apply the same controls to bootstrap files, daily logs, generated skills, consolidation temporary files, and `.rate-limit` state. - Reject a symlinked workspace root and security-sensitive subdirectories such as `memory`, `skills`, and `.rate-limit`.
