T09 · Insecure Skill Coding Practices
Error
- Location
- webhook-server.py:16
- Finding
- Public Webhook Endpoint Accepts Unauthenticated Data-Writing Requests<![CDATA[ ## Vulnerability Details **File Location**: `webhook-server.py:16, 30-35, 112`; `setup-ngrok.sh:44-52`; `omi-webhook-handler.sh:29-40` **Vulnerability Type**: Missing authentication on a publicly exposed webhook **Risk Level**: High ### Vulnerable Code ```python # webhook-server.py WEBHOOK_PORT = int(os.environ.get('OMI_WEBHOOK_PORT', 8765)) WEBHOOK_SECRET = os.environ.get('OMI_WEBHOOK_SECRET', '') # Verify secret if configured if WEBHOOK_SECRET: auth_header = self.headers.get('Authorization', '') if auth_header != f'Bearer {WEBHOOK_SECRET}': self.send_error(401, 'Unauthorized') return ``` ```python # webhook-server.py server = HTTPServer(('0.0.0.0', WEBHOOK_PORT), OmiWebhookHandler) ``` ```bash # setup-ngrok.sh ngrok http $WEBHOOK_PORT --log=stdout > /tmp/ngrok.log 2>&1 & NGROK_PID=$! # Wait for ngrok to start sleep 3 # Get public URL from ngrok API NGROK_URL=$(curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url') ``` ```bash # omi-webhook-handler.sh RECORDING_ID=$(echo "$PAYLOAD" | jq -r '.data.id // .recording_id') CREATED_AT=$(echo "$PAYLOAD" | jq -r '.data.created_at // .created_at // now | strftime("%Y-%m-%dT%H:%M:%SZ")') DATE_DIR=$(echo "$CREATED_AT" | cut -d'T' -f1) REC_DIR="$STORAGE_DIR/$DATE_DIR/$RECORDING_ID" mkdir -p "$REC_DIR" # Save metadata echo "$PAYLOAD" | jq '.data // .' > "$REC_DIR/metadata.json" # Save transcript if available TRANSCRIPT=$(echo "$PAYLOAD" | jq -r '.data.transcript // .transcript // empty') if [[ -n "$TRANSCRIPT" ]]; then echo "$TRANSCRIPT" > "$REC_DIR/transcript.txt" fi ``` ### Technical Analysis Authentication is conditional on `OMI_WEBHOOK_SECRET` being non-empty. The default value is empty, and the supplied startup workflow does not require or automatically create a secret. Consequently, requests are accepted without authentication in the default configuration. The server binds to all network interfaces, and the documented ngrok workflow exposes the ser ...[truncated 1626 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Refuse to start unless a strong webhook secret or signing key is configured. - Authenticate every webhook request rather than treating authentication as optional. - Prefer Omi-supported HMAC signature verification over a static bearer token. - Compare signatures using a constant-time comparison function. - Include timestamps and event identifiers in signature validation to prevent replay attacks. - Bind the server to `127.0.0.1` when ngrok is the intended ingress mechanism. - Configure ngrok access controls where supported. - Apply request rate limits and reject repeated event identifiers. - Document secret generation and secure storage as mandatory setup steps. - Return an error without invoking the handler whenever authentication fails. ]]>
