T09 · Insecure Skill Coding Practices
- Location
scripts/test_runner.sh:127- Finding
Path Traversal and Symlink-Based File Overwrite in Report Generation
- Content
View full analysis
Vulnerability Details
File Location:
scripts/test_runner.sh, lines 127-134
Vulnerability Type: Untrusted path construction and unsafe temporary-file handling
Risk Level: MediumVulnerable Code
bash generate_report() { local skill=$1 local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S") local report_dir="/tmp/skill-tests" local report_file="$report_dir/${skill}_test_report_$(date +%Y%m%d_%H%M%S).json" mkdir -p "$report_dir" cat > "$report_file" <<EOFThe
skillvalue originates from the user-controlled--skillargument:bash --skill) SKILL_NAME="$2" shift 2 ;;Technical Analysis
The script directly embeds the user-controlled Skill name in
report_filewithout validating it as a simple directory name. Shell quoting prevents command injection, but it does not prevent path traversal. A value containing/or..can cause the normalized report path to escape/tmp/skill-tests.The report directory is also a predictable, shared location under
/tmp. The generated filename uses a timestamp with one-second precision and is opened with a normal shell redirection. No exclusive file creation, ownership check, or symlink protection is performed. A local attacker able to write to the report directory may therefore pre-create a symbolic link at a predicted report path.Attack Path
Path traversal scenario:
- An attacker invokes the runner with a crafted Skill value containing traversal components, such as
../../target. - The test commands may fail because the Skill does not exist, but their failures are suppressed with
|| true. generate_reportconstructs a path similar to:/tmp/skill-tests/../../target_test_report_TIMESTAMP.json.- The operating system resolves the traversal components and creates or truncates the resulting file outside the intended report directory.
- The report content is written wit ...[truncated 1049 chars]
- An attacker invokes the runner with a crafted Skill value containing traversal components, such as
- Remediation
View remediation
Remediation Suggestions
-
Validate the Skill name before using it in a path. Permit only a conservative set of characters:
bash if [[ ! "$skill" =~ ^[A-Za-z0-9._-]+$ ]] || [[ "$skill" == "." || "$skill" == ".." ]]; then print_error "Invalid skill name" return 1 fi -
Create a private report directory owned by the current user and restrict its permissions:
bash report_dir="${SKILL_TESTER_REPORT_DIR:-$HOME/.local/state/skill-tests}" install -d -m 0700 -- "$report_dir" -
Resolve the final path and verify that it remains beneath the expected report directory before writing.
-
Create report files atomically and without following existing symbolic links. Use a securely created temporary file in the destination directory, set restrictive permissions, and atomically rename it after writing.
-
Refuse to overwrite existing files and verify that the destination is a regular file owned by the expected user.
-
Avoid predictable shared
/tmppaths. If temporary storage is required, usemktemp -d, register a cleanup trap, and restrict the directory to mode0700.
-
