T09 · Insecure Skill Coding Practices
- Location
scripts/gaggiuino.sh:205- Finding
Unrestricted Persistent API Destination Enables Sensitive Data Redirection and Response Spoofing
- Content
View full analysis
Vulnerability Details
File Location:
scripts/gaggiuino.sh, lines 205–220; the stored value is loaded at lines 23–42 and used for requests at lines 57–90
Vulnerability Type: Insufficient destination validation / server-side request forgery and sensitive data disclosure
Risk Level: MediumVulnerable Code
bash cmd_set_base_url() { local input="${1:?Base URL or host required}" python3 - "$STATE_FILE" "$input" <<'PY' import json, os, re, sys from datetime import datetime, timezone path, raw = sys.argv[1], sys.argv[2].strip() url = raw if re.match(r'^https?://', raw, re.I) else f'http://{raw}' url = url.rstrip('/') os.makedirs(os.path.dirname(path), exist_ok=True) data = { 'preferredBaseUrl': url, 'updatedAt': datetime.now(timezone.utc).isoformat() } with open(path, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) print(json.dumps({'saved': True, 'preferredBaseUrl': url, 'path': path}, ensure_ascii=False, indent=2)) PY }The destination is subsequently used as follows:
bash http_request() { local method="$1" local path="$2" local body_file="$3" local data="${4:-}" local url="${BASE_URL}${path}" if [[ "$method" == "GET" ]]; then status=$(curl -sS --max-time "$TIMEOUT" -o "$body_file" \ -w "%{http_code}" "$url" 2>/dev/null) || curl_rc=$? else if [[ -n "$data" ]]; then status=$(curl -sS --max-time "$TIMEOUT" -X "$method" \ -H "Content-Type: application/json" -d "$data" \ -o "$body_file" -w "%{http_code}" "$url" 2>/dev/null) || curl_rc=$? fi fi }Technical Analysis
set-base-urlaccepts any hostname or URL whose explicit scheme is HTTP or HTTPS. It does not enforce the documented requirement that the destination be a trusted local Gaggiuino endpoint. It also does not resolve and classify the destination IP, reject loopback or cloud metadata addresses, restrict ports, or require approval before persisting the value in:text ...[truncated 2354 chars]- Remediation
View remediation
Remediation Suggestions
-
Enforce an explicit destination policy before saving or using a URL:
- Permit only
.localhostnames or user-approved private/link-local IP addresses. - Reject public IP space, loopback, unspecified, multicast, cloud metadata, and other special-purpose ranges.
- Reject embedded credentials, fragments, unexpected paths, and unapproved ports.
- Permit only
-
Resolve the hostname and validate every returned address. Repeat validation immediately before each request to reduce DNS rebinding risk.
-
Require explicit user confirmation when changing the endpoint and display the normalized hostname, resolved IP, scheme, and port.
-
Maintain an allowlist of approved machine endpoints instead of accepting arbitrary URLs.
-
Disable automatic redirects with
curl --max-redirs 0, or validate every redirect destination before following it. -
Prefer authenticated HTTPS where supported. If the machine only supports HTTP, clearly constrain communication to the validated local network.
-
Apply the same validation when loading the persisted state file, since the file may be edited outside
set-base-url. -
Consider separating read and write endpoint authorization so settings POST requests require an additional confirmation or stronger trust check.
-
