T09 · Insecure Skill Coding Practices
- Location
scripts/analytics-report.sh:69- Finding
Arbitrary Command Execution Through Analytics Report Generation
- Content
View full analysis
Vulnerability Details
File Location:
scripts/analytics-report.sh:69-78,scripts/analytics-report.sh:225-239, andscripts/analytics-report.sh:293-363
Vulnerability Type: Shell command injection through unsafe use ofeval
Risk Level: HighVulnerable Code
The retry helper accepts a command as a string and executes it with
eval:bash retry_file_operation() { local attempt=1 local operation="$1" local description="$2" while [[ $attempt -le $MAX_RETRIES ]]; do log_info "File operation attempt $attempt/$MAX_RETRIES: $description" if eval "$operation"; then log_info "File operation successful on attempt $attempt" return 0 fi if [[ $attempt -lt $MAX_RETRIES ]]; then local delay=${RETRY_DELAYS[$((attempt-1))]} log_warn "File operation failed. Retrying in ${delay}s..." sleep $delay fi ((attempt++)) done log_error "File operation failed after $MAX_RETRIES attempts: $description" return 1 }Values are read from the analytics JSON file without restricting them to safe shell characters:
bash read_json_field() { local field="$1" local default="$2" local result result=$(jq -r ".$field // \"$default\"" "$INPUT_FILE" 2>/dev/null || echo "$default") echo "$result" } TOTAL_IMPRESSIONS=$(read_json_field "summary.total_impressions" "0") TOTAL_ENGAGEMENTS=$(read_json_field "summary.total_engagements" "0") AVG_ER=$(read_json_field "summary.engagement_rate" "0") AVG_CR=$(read_json_field "summary.comment_rate" "0") EXTRACTION_STATUS=$(read_json_field "status" "unknown") POSTS_COUNT=$(read_json_field "posts_count" "0")The JSON-derived values are interpolated into report content and then embedded in a command string passed to the vulnerable helper: ...[truncated 2919 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove
evalentirely. Write the report directly:bash printf '%s\n' "$REPORT_CONTENT" > "$OUTPUT_FILE" -
If retries are required, implement them around a normal function call rather than accepting command strings:
bash write_report() { local output_file="$1" local content="$2" printf '%s\n' "$content" > "$output_file" } -
Pass operations and arguments as separate array elements. Never concatenate data into executable shell syntax.
-
Enforce JSON types before using values. Require metric fields to be JSON numbers and restrict status to an explicit allowlist such as
success,failed, orunknown. -
Treat analytics files as untrusted input even if they are normally generated locally. Restrict directory and file permissions so unrelated users and processes cannot modify them.
-
Add regression tests containing shell metacharacters, command substitutions, quotes, newlines, and redirections, and verify that these values are rendered literally without execution.
-
