dograh/scripts
prabhatlepton 58cc9c8b1c
fix(web): honor X-Forwarded-Proto in uvicorn so request.url is https behind a reverse proxy (#515)
* fix(web): honor X-Forwarded-Proto in uvicorn so request.url is https behind a reverse proxy

## Problem

When Dograh runs behind a TLS-terminating reverse proxy (Cloudflare →
Traefik in Kubernetes, nginx in the docker-compose install), the inside
of the cluster/host is plain HTTP. Uvicorn defaults to trusting
`scope["scheme"]` from the socket, so `request.url.scheme` reads `http`
even though the client dialed `https`.

That breaks any code path that hashes or echoes the request URL back to
the caller. Concrete symptom seen in production: **Vobiz inbound webhook
signatures fail with "signature validation failed for vobiz"** because
Vobiz computes HMAC over the URL it dialed (`https://.../inbound/run`)
while Dograh recomputes it as `http://...`.  Log excerpt from the
failing call:

```
WARNING | provider.py | Vobiz webhook signature mismatch.
         Expected: daOpAZPm..., Got: 1+eW/RxE...
WARNING | telephony.py | /inbound/run: signature validation failed for vobiz
```

Twilio, Plivo and any other provider that signs over the callback URL
have the same failure mode when Dograh is deployed behind a proxy.

## Fix

Start uvicorn with `--proxy-headers --forwarded-allow-ips="*"` in
`scripts/run_web.sh`. Uvicorn rewrites `scope["scheme"]` and client
address from `X-Forwarded-Proto` / `X-Forwarded-For` when the request
originates from a trusted upstream — Traefik and Cloudflare set both
correctly, so `request.url.scheme == "https"` inside the app once again
and provider signature checks pass.

Verified end-to-end on a production k3s install (Traefik + Cloudflare
edge → dograh-web pod) — after the change, the very next Vobiz inbound
webhook validated successfully and the call connected past the previous
11-second signature-failure hangup.

* address review: let operators narrow FORWARDED_ALLOW_IPS

Both bot reviewers on #515 flagged `--forwarded-allow-ips="*"` as a
defence-in-depth concern: if uvicorn is directly reachable from an
untrusted network (bypassing the proxy), any client can spoof
`X-Forwarded-Proto` / `X-Forwarded-For`, and uvicorn will rewrite
`request.client` / `request.url` from those attacker-controlled headers.

Fix: consume `FORWARDED_ALLOW_IPS` from the environment (uvicorn already
recognizes this env var; see `deploy/hostinger/docker-compose.yaml:179`
for the existing precedent). Default stays `"*"` so the behavior of the
original fix is preserved for the standard docker-compose / helm layouts
where the app pod is only reachable via the proxy Service. Operators
who terminate uvicorn on a host that's also reachable directly can
narrow it to the proxy CIDR:

  FORWARDED_ALLOW_IPS="10.42.0.0/16" ./scripts/run_web.sh

* address review: declare FORWARDED_ALLOW_IPS in the helm chart, not the script

uvicorn already enables proxy-header handling by default and falls back to
the FORWARDED_ALLOW_IPS env var when --forwarded-allow-ips is absent, so the
CLI flags were redundant and the script-level "*" default hid a
security-relevant trust decision away from operators. Drop the flags, keep
run_web.sh deployment-agnostic, and declare the env var where the other
deployment config lives — web.forwardedAllowIps in values.yaml (default "*",
narrowable to a proxy CIDR) — mirroring how docker-compose already sets it
on the api service.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* simplify run_web.sh comment

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: prabhat pankaj <prabhatiitbhu@gmail.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 10:26:45 +05:30
..
lib feat(scripts): free trusted HTTPS via sslip.io for public-IP remote i… (#460) 2026-06-27 17:19:29 +05:30
AGENTS.md feat(scripts): free trusted HTTPS via sslip.io for public-IP remote i… (#460) 2026-06-27 17:19:29 +05:30
CLAUDE.md chore: add powershell version for setup_local 2026-05-14 15:01:11 +05:30
dump_docs_openapi.py chore: update documentation for telephony 2026-05-02 16:59:17 +05:30
format.sh feat: add openai realtime models (#298) 2026-05-16 18:05:23 +05:30
generate_sdk.sh feat: add Tuner Integration to Dograh (#311) 2026-05-20 14:37:33 +05:30
lint.sh Add alembic and start services scripts 2025-09-26 09:09:06 +05:30
makemigrate.ps1 Feat/add developer docs for windows (#213) 2026-04-03 07:04:13 +05:30
makemigrate.sh Add alembic and start services scripts 2025-09-26 09:09:06 +05:30
migrate.ps1 Feat/add developer docs for windows (#213) 2026-04-03 07:04:13 +05:30
migrate.sh Add alembic and start services scripts 2025-09-26 09:09:06 +05:30
pre_commit.sh Add alembic and start services scripts 2025-09-26 09:09:06 +05:30
prepare-slack-message.sh fix: slack message body (#59) 2025-11-22 13:59:07 +05:30
release_sdks.sh chore: release sdks 2026-05-31 17:13:42 +05:30
rolling_update.sh chore: drain active calls before rolling updates (#474) 2026-06-29 06:00:31 +05:30
run_ari_manager.sh feat: add Helm chart for Kubernetes deployment (#365) 2026-07-03 12:39:39 +05:30
run_arq_worker.sh feat: add Helm chart for Kubernetes deployment (#365) 2026-07-03 12:39:39 +05:30
run_campaign_orchestrator.sh feat: add Helm chart for Kubernetes deployment (#365) 2026-07-03 12:39:39 +05:30
run_dograh_init.sh chore: refactor setup scrpts (#288) 2026-05-14 14:45:34 +05:30
run_migrate.sh feat: add Helm chart for Kubernetes deployment (#365) 2026-07-03 12:39:39 +05:30
run_web.sh fix(web): honor X-Forwarded-Proto in uvicorn so request.url is https behind a reverse proxy (#515) 2026-07-16 10:26:45 +05:30
setup-worktree.sh chore: setup worktree on folder open 2026-06-30 16:15:10 +05:30
setup_custom_domain.sh fix: restore invoking user's ownership after sudo deploy scripts 2026-07-14 18:05:13 +05:30
setup_fork.ps1 feat: add devcontainer based setup (#352) 2026-05-25 20:44:22 +05:30
setup_fork.sh feat: add devcontainer based setup (#352) 2026-05-25 20:44:22 +05:30
setup_local.devcontainer.md feat: add devcontainer based setup (#352) 2026-05-25 20:44:22 +05:30
setup_local.ps1 feat(scripts): free trusted HTTPS via sslip.io for public-IP remote i… (#460) 2026-06-27 17:19:29 +05:30
setup_local.sh feat(scripts): free trusted HTTPS via sslip.io for public-IP remote i… (#460) 2026-06-27 17:19:29 +05:30
setup_pipecat.sh chore: update documentation 2026-06-19 18:11:35 +05:30
setup_remote.sh fix: restore invoking user's ownership after sudo deploy scripts 2026-07-14 18:05:13 +05:30
setup_requirements.ps1 chore: update documentation 2026-06-19 18:11:35 +05:30
setup_requirements.sh chore: update documentation 2026-06-19 18:11:35 +05:30
start_docker.ps1 fix: Windows PowerShell 5.1 start_docker crash and paste-safe docs snippets 2026-07-01 15:54:11 +05:30
start_docker.sh feat(scripts): free trusted HTTPS via sslip.io for public-IP remote i… (#460) 2026-06-27 17:19:29 +05:30
start_services.sh chore: drain active calls before rolling updates (#474) 2026-06-29 06:00:31 +05:30
start_services_dev.ps1 feat: add devcontainer based setup (#352) 2026-05-25 20:44:22 +05:30
start_services_dev.sh feat: add devcontainer based setup (#352) 2026-05-25 20:44:22 +05:30
start_services_docker.sh feat: an option to setup remote server with docker compose build (#280) 2026-05-13 17:22:14 +05:30
stop_services.ps1 Feat/add developer docs for windows (#213) 2026-04-03 07:04:13 +05:30
stop_services.sh feat: add rolling updates for production deployment (#175) 2026-03-02 14:44:04 +05:30
update_remote.sh fix: restore invoking user's ownership after sudo deploy scripts 2026-07-14 18:05:13 +05:30
worktree-assign-port.sh chore: setup worktree script 2026-06-30 15:59:18 +05:30