fix(learner): SPA proxy forwards no credentials and never goes through HTTP_PROXY
spaWithCsp proxies GET and HEAD only (405 otherwise, no body buffering) and forwards only accept, if-none-match, if-modified-since and range. The internal server listens on a Unix socket in a private 0700 temp dir. Bun 1.3.14 ignores proxy: false for this hop, and over a socket with a proxy set it sends an absolute-form target that breaks asset routing, so localhost, 127.0.0.1 and ::1 are appended to NO_PROXY/no_proxy (existing entries kept). accept-encoding is no longer forced; fetch decompresses and the encoding headers are dropped. Test: in a subprocess with HTTP(S)_PROXY and ALL_PROXY set to a dead proxy, the SPA and an asset load with the CSP, POST gets 405, and the upstream sees no Cookie, Authorization or X-Forwarded-For. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c7b9e1f98e
commit
213f2247b4
3 files changed
+125
-12
No files matched your search
@@ -63,3 +63,25 @@ test("the runner frame is served sandboxed, with no connections and only its own
|
||||
expect(scriptSrc(csp)).toMatch(/^script-src 'sha256-[A-Za-z0-9+/=]+' blob:$/);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
test("the SPA proxy ignores HTTP_PROXY/ALL_PROXY and forwards no credentials", () => {
|
||||
const dead = "http://127.0.0.1:9"; // nothing listens on the discard port
|
||||
const p = Bun.spawnSync([process.execPath, new URL("./e2e/spa-proxy-check.ts", import.meta.url).pathname], {
|
||||
env: { ...process.env, HTTP_PROXY: dead, http_proxy: dead, HTTPS_PROXY: dead, https_proxy: dead, ALL_PROXY: dead, all_proxy: dead, NO_PROXY: "corp.example", no_proxy: "" },
|
||||
stdout: "pipe", stderr: "pipe",
|
||||
});
|
||||
expect(p.exitCode).toBe(0);
|
||||
const out = JSON.parse(p.stdout.toString().trim().split("\n").pop()!);
|
||||
// The environment proxy really is in effect for plain fetches in that process...
|
||||
expect(out.controlViaEnvProxy).not.toBe("status 200");
|
||||
// ...but the SPA still loads through spaWithCsp, with its CSP.
|
||||
expect(out.status).toBe(200);
|
||||
expect(out.body).toContain('<div id="root">');
|
||||
expect(out.csp).toContain("script-src 'self'");
|
||||
expect(out.post).toBe(405);
|
||||
// Assets come through too (with a proxy in the env, Bun's socket fetch would otherwise hit the HTML fallback).
|
||||
expect(out.asset).toBe("200 text/javascript console.log(1)");
|
||||
expect(out.noProxy).toBe("corp.example,localhost,127.0.0.1,::1");
|
||||
// The upstream saw only the allowlisted headers: no Cookie, Authorization or X-Forwarded-*.
|
||||
expect(out.seen).toEqual([{ cookie: null, authorization: null, xff: null, accept: "text/html" }]);
|
||||
}, 30_000);
|
||||
Reference in new issue
Block a user