T09 · Insecure Skill Coding Practices
- Location
scripts/extract-skill.sh:107- Finding
Symbolic-Link Traversal Allows Writes Outside the Intended Workspace
- Content
View full analysis
Vulnerability Details
File Location:
scripts/extract-skill.sh, lines 107–121 and 171–177
Vulnerability Type: Symbolic-link path traversal and time-of-check/time-of-use weakness
Risk Level: MediumVulnerable Code
bash # Validate output path to avoid writes outside current workspace. if [[ "$SKILLS_DIR" = /* ]]; then log_error "Output directory must be a relative path under the current directory." exit 1 fi if [[ "$SKILLS_DIR" =~ (^|/)\.\.(/|$) ]]; then log_error "Output directory cannot include '..' path segments." exit 1 fi SKILLS_DIR="${SKILLS_DIR#./}" SKILLS_DIR="./$SKILLS_DIR" SKILL_PATH="$SKILLS_DIR/$SKILL_NAME" # Create skill directory structure log_info "Creating skill: $SKILL_NAME" mkdir -p "$SKILL_PATH" # Create SKILL.md from template cat > "$SKILL_PATH/SKILL.md" << TEMPLATETechnical Analysis
The script claims to constrain
--output-dirto the current workspace. It rejects absolute paths and lexical..path segments, but it does not resolve the canonical destination or inspect path components for symbolic links.Consequently, a syntactically relative output directory can resolve to a location outside the current workspace. The checks validate only the user-provided string, while
mkdirand shell redirection follow symbolic links during filesystem operations.There is also a time-of-check/time-of-use window because validation and file creation are separate operations. A path component could potentially be replaced with a symbolic link after validation but before directory or file creation.
Attack Path
-
An attacker who can create or modify entries in the working directory creates a symbolic link pointing outside the workspace:
bash ln -s /home/victim/.config external -
The extraction helper is invoked using the relative symbolic-link path:
bash ./scripts/extract-skill.sh injected --output-dir external -
The path passes validation because it is re ...[truncated 1061 chars]
-
- Remediation
View remediation
Remediation Suggestions
-
Resolve the current workspace to a canonical path before processing the destination:
bash WORKSPACE_ROOT="$(realpath -e .)" -
Canonicalize the nearest existing parent of the requested output directory and verify that it remains beneath
WORKSPACE_ROOT. Perform a path-component-aware comparison rather than a simple textual prefix check. -
Reject symbolic links in every existing output-path component. For example, walk each component with
lstatortest -Lbefore creating directories. -
Revalidate the canonical destination immediately before writing. Do not rely solely on rejecting absolute paths and
..segments. -
Reduce the race condition by using descriptor-relative, no-follow filesystem operations where available. A small helper implemented with
openat/mkdiratandO_NOFOLLOWwould provide stronger protection than ordinary shell redirection. -
Refuse existing destinations of unexpected types, including symbolic links and non-directory path components.
-
Add regression tests covering:
- An absolute output path.
- A path containing
... - A relative symlink pointing outside the workspace.
- A nested path containing a symlink component.
- Replacement of a checked directory with a symlink before creation.
- A valid relative directory wholly contained within the workspace.
-
