T09 · Insecure Skill Coding Practices
- Location
SKILL.md:198- Finding
Unsafe Task Identifier Interpolation in Shell-Based Subprocess Scheduler
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 198–208
Vulnerability Type: Command injection and path traversal caused by unsafe shell interpolation
Risk Level: HighVulnerable code:
bash cat "$research_dir/tasks.txt" | parallel -j $max_parallel \ "timeout 600 claude -p \"\$(cat $research_dir/prompts/{}.md)\" \ --allowedTools 'Read,Write,Edit,Bash,WebFetch,WebSearch' \ --output-format json > $research_dir/child_outputs/{}.json 2>&1" # Or use background tasks for task_id in $(cat "$research_dir/task_ids.txt"); do ( timeout 600 claude -p "$(cat "$research_dir/prompts/$task_id.md")" \ --allowedTools "Read,Write,Edit,Bash,WebFetch,WebSearch" \ --output-format json \ > "$research_dir/child_outputs/$task_id.json" 2>&1 ) &Technical Analysis
The GNU Parallel template substitutes
{}directly into a shell command string without validating or safely passing the task identifier as an argument. If a task identifier contains shell metacharacters, command substitutions, redirection operators, whitespace, or quoting characters, those characters may alter the generated shell command.The background-task alternative reads identifiers using
for task_id in $(cat ...), which performs command substitution followed by shell word splitting and pathname expansion. The identifier is then embedded in prompt and output paths without validation or canonical containment checks. Values containing directory separators or traversal sequences such as../can consequently resolve outside the intendedprompts/orchild_outputs/directories.This becomes exploitable when task identifiers are derived from user-controlled input or externally collected research data and are written to
tasks.txtortask_ids.txtwithout strict normalization.Attack Path
- An attacker supplies or influences a research subtarget that becomes a ta ...[truncated 1494 chars]
- Remediation
View remediation
Remediation Suggestions
-
Generate internal task identifiers rather than using raw user-provided labels. Enforce a strict allowlist such as
^[A-Za-z0-9_-]+$and reject empty values, whitespace, path separators, traversal components, shell metacharacters, and control characters. -
Replace
for task_id in $(cat ...)with a line-preserving reader:bash while IFS= read -r task_id; do # Validate task_id before use. done < "$research_dir/task_ids.txt" -
Move task execution into a fixed worker script and pass the identifier as a positional argument. Invoke that script through GNU Parallel without constructing a nested shell command from untrusted text.
-
Quote every variable expansion, including
"$max_parallel", and use--where supported to prevent values from being interpreted as options. -
Resolve prompt and output paths to canonical absolute paths and verify that each remains beneath the canonical research directory before reading or writing.
-
Create output files with restrictive permissions and refuse symbolic links or unexpected existing file types where supported.
-
Add negative tests covering identifiers with spaces, newlines,
../, quotes, semicolons, command substitutions, redirection operators, wildcard characters, and leading hyphens. -
Retain least-privilege
--allowedToolssettings for each child task and removeBashor network tools whenever the specific subtask does not require them.
-
