T09 · Insecure Skill Coding Practices
- Location
- scripts/handoff_file.sh:159
- Finding
- Path Traversal in Handoff Package Resolution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/handoff_file.sh:159-163` **Vulnerability Type**: Improper path validation and path traversal **Risk Level**: Medium ### Vulnerable Code ```bash resolve) id="${1:-}" [ -n "$id" ] || { echo "Usage: handoff_file.sh resolve <handoff_id>" >&2; exit 1; } target="$HANDOFF_ROOT/$id/handoff.md" [ -f "$target" ] || { echo "Handoff not found: $id" >&2; exit 1; } printf '%s\n' "$target" ;; ``` ### Technical Analysis The `resolve` operation directly interpolates the user-controlled `id` into a filesystem path without validating that it matches the generated handoff identifier format. It also does not canonicalize the resulting path or verify that it remains beneath `HANDOFF_ROOT`. An identifier containing traversal components such as `../` can therefore escape the configured handoff directory. The `[ -f "$target" ]` check only verifies that the resolved target is a regular file; it does not enforce the intended directory boundary. Symbolic links beneath `HANDOFF_ROOT` can produce the same boundary violation. Exploitation is constrained to accessible targets whose final filename is `handoff.md`, but a matching file outside the storage root can be resolved and subsequently read by the Agent. Because handoff documents are interpreted as persistent task state, an attacker-controlled document can also supply misleading constraints, file references, or next-step instructions. ### Attack Path 1. An attacker creates or identifies an accessible file outside `HANDOFF_ROOT` named `handoff.md`. 2. The attacker provides a crafted handoff identifier containing traversal components, for example: ```text handoff in ../../path/to/package ``` 3. The Skill invokes: ```bash scripts/handoff_file.sh resolve "../../path/to/package" ``` 4. The script constructs: ```text $HANDOFF_ROOT/../../path/to/package/handoff.md ``` 5. Because no canonical containment check is performed, the script ac ...[truncated 1207 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Validate the identifier against the exact generated format before using it: ```bash if [[ ! "$id" =~ ^[0-9]{8}-[0-9]{4}-[0-9a-f]{8}$ ]]; then echo "Invalid handoff ID." >&2 exit 1 fi ``` 2. Canonicalize both the storage root and target path, then enforce containment: ```bash root_real="$(realpath "$HANDOFF_ROOT")" target_real="$(realpath "$HANDOFF_ROOT/$id/handoff.md")" case "$target_real" in "$root_real"/*) ;; *) echo "Handoff path escapes storage root." >&2 exit 1 ;; esac ``` 3. Reject symbolic-link package directories or files if links are not required: ```bash package_dir="$HANDOFF_ROOT/$id" [ ! -L "$package_dir" ] || { echo "Symbolic-link handoff directories are not permitted." >&2 exit 1 } [ ! -L "$package_dir/handoff.md" ] || { echo "Symbolic-link handoff files are not permitted." >&2 exit 1 } ``` 4. Apply equivalent canonical-path and containment checks to all operations that enumerate, select, create, or read handoff packages. 5. Preserve the existing user-confirmation requirement before executing recovered actions, and clearly label handoff contents as untrusted persisted data rather than authoritative instructions. ]]>
