T09 · Insecure Skill Coding Practices
Error
- Location
- App/webhook.py:64
- Finding
- Authentication Bypass on the Raw Webhook Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `App/webhook.py:64-74` **Vulnerability Type**: Missing authentication on a security-sensitive endpoint **Risk Level**: High ### Vulnerable Code ```python @router.post("/webhook/raw") async def receive_raw_webhook(request: Request): """ Raw webhook endpoint — always uses key-value formatter. Useful for non-trading alerts (uptime monitors, CI/CD, etc.) """ try: payload: dict[str, Any] = await request.json() except Exception: raise HTTPException(status_code=400, detail="Invalid JSON payload") message = format_raw(payload) await send_message(message) return {"status": "ok"} ``` ### Technical Analysis The primary `/webhook` route validates the `X-Webhook-Secret` header before forwarding a message. The `/webhook/raw` route performs the same security-sensitive Telegram forwarding operation but never invokes `verify_secret` and does not otherwise authenticate the caller. Consequently, configuring `WEBHOOK_SECRET` does not protect all message-sending routes. This is an endpoint-level authorization bypass rather than merely an insecure default. ### Attack Path 1. An operator deploys the service and configures `WEBHOOK_SECRET`, expecting webhook forwarding to be protected. 2. The service exposes port 8000, including `/webhook/raw`. 3. An attacker submits arbitrary JSON without an `X-Webhook-Secret` header: ```http POST /webhook/raw HTTP/1.1 Content-Type: application/json {"Urgent security alert": "Visit the attacker-controlled link immediately"} ``` 4. The service formats the attacker-controlled JSON. 5. The service sends the resulting message to the configured Telegram chat using the victim's bot credentials. ### Impact Assessment A remote unauthenticated attacker can inject arbitrary messages into the configured Telegram chat. This permits forged operational or trading alerts, phishing content, alert-channel spam, social engineering, and c ...[truncated 252 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Require authentication on `/webhook/raw` using the same verification mechanism as `/webhook`. - Implement authentication as a shared FastAPI dependency or router-level dependency so new message-sending routes cannot accidentally omit it. - Use a non-optional header type when a secret is required. - Add tests proving that both endpoints return `401 Unauthorized` for missing or incorrect secrets. Example hardening pattern: ```python async def require_webhook_secret( x_webhook_secret: str | None = Header(default=None), ) -> None: if not verify_secret(x_webhook_secret): raise HTTPException(status_code=401, detail="Invalid webhook secret") @router.post("/webhook/raw", dependencies=[Depends(require_webhook_secret)]) async def receive_raw_webhook(request: Request): ... ``` ]]>
