T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/setup-webhook.sh:6
- Finding
- Persistent Disclosure of Sensitive Meeting Data to an Arbitrary Webhook Destination<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup-webhook.sh:6-9, 22-28, 47-56, 71-81` **Vulnerability Type**: Arbitrary webhook destination with excessive default data scope **Risk Level**: High ### Complete Code Snippet ```bash WEBHOOK_URL="" INCLUDE_TRANSCRIPT=true INCLUDE_SUMMARY=true INCLUDE_ACTION_ITEMS=true # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --url) WEBHOOK_URL="$2"; shift 2 ;; --no-transcript) INCLUDE_TRANSCRIPT=false; shift ;; --no-summary) INCLUDE_SUMMARY=false; shift ;; --no-action-items) INCLUDE_ACTION_ITEMS=false; shift ;; if [ -z "$WEBHOOK_URL" ]; then echo "❌ Webhook URL required" echo "Usage: setup-webhook.sh --url https://your-domain.com/webhook" exit 1 fi if [[ ! "$WEBHOOK_URL" =~ ^https:// ]]; then echo "❌ Webhook URL must be HTTPS" exit 1 fi # Register webhook RESPONSE=$(curl -s -X POST "https://api.fathom.ai/external/v1/webhooks" \ -H "X-API-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"destination_url\": \"$WEBHOOK_URL\", \"include_transcript\": $INCLUDE_TRANSCRIPT, \"include_summary\": $INCLUDE_SUMMARY, \"include_action_items\": $INCLUDE_ACTION_ITEMS, \"triggered_for\": [\"my_recordings\", \"shared_external_recordings\", \"my_shared_with_team_recordings\", \"shared_team_recordings\"] }") ``` ### Technical Analysis The script creates a persistent Fathom webhook whose destination is entirely controlled by the `--url` argument. Validation only checks whether the supplied string begins with `https://`. HTTPS provides transport encryption, but it does not establish that the receiving domain is owned or trusted by the user. The webhook enables transcripts, summaries, and action items by default. It also subscribes to four broad recording scopes, including externally shared and team-shared recordings. This exceeds a least-privilege configuration because sensitive content is ...[truncated 2116 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Use privacy-preserving defaults** - Initialize `INCLUDE_TRANSCRIPT`, `INCLUDE_SUMMARY`, and `INCLUDE_ACTION_ITEMS` to `false`. - Require explicit opt-in flags such as `--include-transcript`. - Default to the narrowest recording scope. 2. **Require explicit recording-scope selection** - Add flags for each supported `triggered_for` scope. - Do not automatically include external or team-shared recordings. - Clearly identify scopes that may contain third-party data. 3. **Confirm sensitive registration** - Display the normalized destination, selected scopes, and data categories before registration. - Require interactive confirmation. - Permit noninteractive registration only through an explicit option such as `--yes`, accompanied by documentation of the risks. 4. **Verify or restrict webhook destinations** - Prefer an administrator-configured allowlist of approved domains. - Where supported, require a destination ownership challenge before enabling delivery. - Parse the URL structurally rather than relying only on a prefix test. - Reject embedded credentials and malformed destinations. 5. **Construct the request safely** - Generate JSON with `jq` rather than interpolating the URL into a JSON string: ```bash PAYLOAD=$(jq -n \ --arg url "$WEBHOOK_URL" \ --argjson transcript "$INCLUDE_TRANSCRIPT" \ --argjson summary "$INCLUDE_SUMMARY" \ --argjson actions "$INCLUDE_ACTION_ITEMS" \ --argjson scopes "$TRIGGER_SCOPES" \ '{ destination_url: $url, include_transcript: $transcript, include_summary: $summary, include_action_items: $actions, triggered_for: $scopes }') ``` - Submit it using `curl --data-binary "$PAYLOAD"`. 6. **Improve lifecycle controls** - Provide a dedicated webhook listing and deletion command. - Clearly document that registration persists after the script ...[truncated 424 chars]
