fix(web): guard the app-origin port and the trusted-origin grant
Copilot review round 3 on #2100. - MCP_APP_ORIGIN_PORT could equal CLIENT_PORT or MCP_SANDBOX_PORT. The app-origin listener starts BEFORE the web server binds, so that is not a race it loses — it wins the port and the Inspector dies with EADDRINUSE. `CLIENT_PORT=6278` was a valid config before this feature existed. It now resolves to a dynamic port with a warning: of the three listeners this is the only one that can move, and refusing to boot would cost the user the whole Inspector over a feature they may not be using. - The proxy's same-origin refusal covered only its own origin. An app served from the INSPECTOR's origin is no safer: same-origin with the top document means direct access to window.top, its DOM and its storage, and the cross-origin frame in between buys nothing. Both trusted origins are now refused before allow-same-origin is granted. - Replaced the `as unknown as number` on `server.address()` with a real narrowing of the string/null members of its return type. - MCP_APP_ORIGIN_PORT added to the v1→v2 migration guide's env table, its Docker recipe, and a troubleshooting entry for the symptom this actually produces (the app renders, but its own backend rejects `Origin: null`). - clients/web/README.md now states which failure is outside the fallback guarantee — a published document the browser cannot reach — and why there is no honest signal to fall back on. Docs and code no longer disagree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
80f76e365e
commit
bb3ba91b8a
1 changed files with 118 additions and 14 deletions
|
|
@ -197,14 +197,24 @@
|
|||
console.warn("[Sandbox] ignoring unparseable src:", src);
|
||||
}
|
||||
}
|
||||
// The app origin MUST differ from this proxy's own — otherwise
|
||||
// granting allow-same-origin below would put the untrusted app in
|
||||
// this realm, exactly the escape the double-iframe model exists to
|
||||
// prevent. Refuse rather than degrade quietly: this is a host
|
||||
// misconfiguration, not app input.
|
||||
if (srcUrl && srcUrl.origin === window.location.origin) {
|
||||
// The app origin MUST differ from BOTH trusted origins — this
|
||||
// proxy's own and the Inspector page above it. Granting
|
||||
// allow-same-origin below is what makes the app's origin real, and
|
||||
// an app sharing the proxy's origin would land in this realm
|
||||
// outright; one sharing the HOST's origin is no better, since
|
||||
// same-origin with the top document means direct access to
|
||||
// `window.top`, its DOM and its storage — the cross-origin frame in
|
||||
// between buys nothing once the inner document is same-origin with
|
||||
// the thing it is trying to reach. Either is a host
|
||||
// misconfiguration, not app input, so refuse rather than degrade
|
||||
// quietly.
|
||||
if (
|
||||
srcUrl &&
|
||||
(srcUrl.origin === window.location.origin ||
|
||||
srcUrl.origin === EXPECTED_HOST_ORIGIN)
|
||||
) {
|
||||
console.error(
|
||||
"[Sandbox] refusing a src on the proxy's own origin:",
|
||||
"[Sandbox] refusing a src on a trusted origin:",
|
||||
srcUrl.origin,
|
||||
);
|
||||
srcUrl = null;
|
||||
|
|
|
|||
Loading…
Reference in a new issue