T09 · Insecure Skill Coding Practices
- Location
scripts/script.sh:84- Finding
Unquoted User Input Enables curl Option Injection and Local File Exfiltration
- Content
View full analysis
Vulnerability Details
File Location:
scripts/script.sh, lines 84-100
Vulnerability Type: curl argument and option injection
Risk Level: HighVulnerable Code
bash cmd_http() { local url="${2:-}" local count="${3:-}" [ -z "$url" ] && die "Usage: $SCRIPT_NAME http <url count>" echo 'Testing $2 ($((${3:-5})) requests)'; for i in $(seq 1 ${3:-5}); do curl -so /dev/null -w '%{time_total}' $2 2>/dev/null; echo; done | awk '{s+=$1;n++} END{printf "Avg: %.3fs\n",s/n}' } cmd_latency() { local host="${2:-}" [ -z "$host" ] && die "Usage: $SCRIPT_NAME latency <host>" curl -so /dev/null -w 'DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n' $2 2>/dev/null } cmd_throughput() { local url="${2:-}" [ -z "$url" ] && die "Usage: $SCRIPT_NAME throughput <url>" curl -so /dev/null -w '%{speed_download}' $2 2>/dev/null | awk '{printf "Speed: %.0f bytes/sec\n",$1}' }Technical Analysis
The
http,latency, andthroughputhandlers pass the user-controlled$2positional parameter tocurlwithout quoting it and without using the--end-of-options delimiter. Bash consequently performs word splitting and pathname expansion before invokingcurl.An attacker can supply a single argument containing spaces and curl options. After shell expansion, curl receives those words as independent command-line arguments rather than as one URL. Options such as
--data-binary @FILE,--upload-file FILE, or--config FILEcan cause curl to read local resources and transmit their contents to an attacker-controlled server.The handlers also use incorrect positional parameters.
mainremoves the command name withshiftbefore invoking each handler, but the handlers read the primary value from$2rather than$1. This breaks documented invocations, but does ...[truncated 1445 chars]- Remediation
View remediation
Remediation Suggestions
- Correct positional-argument handling after
mainperformsshift. Read the primary argument from$1and the optional count from$2. - Store arguments in local variables and quote every expansion.
- Insert
--before the URL so curl cannot interpret it as an option. - Reject values beginning with
-. - Parse and validate URLs, allowing only explicitly supported schemes such as
http://andhttps://. - Validate request counts as bounded positive integers before passing them to
seq. - Consider restricting access to loopback, link-local, private, and cloud metadata addresses if untrusted users can select targets.
Example hardened implementation:
bash cmd_throughput() { local url="${1:-}" [ -z "$url" ] && die "Usage: $SCRIPT_NAME throughput <url>" case "$url" in http://*|https://*) ;; *) die "Only HTTP and HTTPS URLs are supported" ;; esac curl -so /dev/null -w '%{speed_download}' -- "$url" 2>/dev/null | awk '{printf "Speed: %.0f bytes/sec\n", $1}' }Apply the same quoting, validation, corrected indexing, and
--delimiter pattern to every affected curl invocation.- Correct positional-argument handling after
