Repository navigation
fix: webhook and MCP URLs use https behind an HTTPS proxy (#3601, #2907) - #3811
Conversation
The schedule webhook URL came from request.base_url and the auto-detected MCP URL hardcoded http://<host>:8080, so a TLS install behind a proxy advertised http:// for both. Both now take their origin from utils.public_url.public_base_url, which upgrades to https on the proxy's X-Forwarded-Proto and never downgrades. Behind an HTTPS proxy the MCP default is https://<host>/mcp, since the frontend nginx serves /mcp on the same origin. The API Keys page now takes the server-detected MCP URL when it is https, and keeps its hostname guess otherwise (behind the Vite dev proxy the backend sees its own host). uvicorn proxy-header trust is unchanged: enabling it would also change request.client.host for every per-IP limiter, and agents share the network with the frontend nginx. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/review: pre-landing reviewBranch:
Execution coverage
Fix mutation: with Critical findingsNone. Informational[I1] Test gap: the [I2] Header trust is upgrade-only and caller-scoped (Confidence 8/10, no action) Clean categories
Summary
🤖 Generated with Claude Code |
PR Validation ReportPR: #3811 - fix: webhook and MCP URLs use https behind an HTTPS proxy (#3601, #2907)
Execution coverage (§5.4)
Fix mutation: with the two backend files reverted, 9 of 14 new tests go red. Issues
RecommendationAPPROVE for #2907 and the webhook half of #3601, pending a human review. #3601 stays open for the decision in the PR body. 🤖 Generated with Claude Code |
Summary
https://when the reverse proxy reports an HTTPS connection (X-Forwarded-Proto: https).utils/public_url.public_base_urlhelper from fix(nevermined): card (fiat) plans can't be paid — the 402 and verify/settle always use the nvm:erc4337 scheme #3215. It reads the raw header and only ever upgrades http to https, so the payment links, the webhook URL and the MCP URL follow one rule.https://<host>/mcp, with no:8080, because the frontend nginx serves/mcpon the same origin. Without the header, or on localhost, the MCP URL is unchanged.@AndriiPasternak31 — the compose / proxy-trust part of #3601 is not in this PR
Your comment on #3601 and its second acceptance criterion ask for
--proxy-headerswith a forwarded-allow-ips value scoped to the proxy. This PR leaves that out on purpose. The reasons:request.client.hostfromX-Forwarded-For. That changes the IP every per-IP limiter and audit row sees (CSO 2026-09-30, finding 16).trinity-agent-networknext to the agents and has no fixed IP. A value that trusts nginx therefore also trusts any agent, unless we first pin static IPs for frontend and cloudflared.So #3601's first criterion (
https://webhook URL and curl sample) is met here, and its second is not. Can you either agree to split the compose change into its own issue, or say the scoped trust is still needed for 1.0? This PR leaves #3601 open. #2907 closes.X-Forwarded-Host: the hostname stays theHostheader. The frontend nginx forwards the client's$host, and no other route in the codebase trustsX-Forwarded-Host.Changes
src/backend/routers/schedules.py:_build_webhook_url(request, token)usespublic_base_url, and returnsNonewith no usable host. All four call sites pass the request.src/backend/routers/settings/mcp_url.py:_get_default_mcp_urlreturnshttps://<host>/mcpbehind an HTTPS proxy. A stored override still wins inresolve_mcp_url.src/frontend/src/components/settings/McpKeysTab.vue: uses the httpsdefault_urlfrom the server.src/frontend/src/views/Settings.vue: the MCP panel hint names the proxy scheme.docs/DEPLOYMENT.md(TLS section),feature-flows/webhook-triggers.md,feature-flows/api-keys-page.md, and the CSO diff report.Test Plan
cd tests && pytest unit/test_3601_2907_proxy_scheme_urls.py -vgives 14 passed. 8 were red before the fix.webhook or mcp_url or public_base_url or settings_package or connector or schedule).test_3215_plan_scheme.pyandtest_3215_task_metadata.pywere excluded because they cannot be imported with the localpayments_pyversion. That is the same ondev.https://.Fixes #2907
Refs #3601
🤖 Generated with Claude Code