// The dev server's /api proxy adds the daemon token and drops Origin, so only // it can refuse a page of another origin; a daemon E2E never runs through Vite. import assert from 'node:assert/strict'; import { mkdtemp, rm, writeFile } from 'node:fs/promises'; import { createServer as createHttpServer, request } from 'node:http'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { after, before, test } from 'node:test'; import { fileURLToPath } from 'node:url'; import { createServer } from 'vite'; const web = fileURLToPath(new URL('..', import.meta.url)); const reached = []; const daemon = createHttpServer((req, res) => { reached.push({ url: req.url, headers: req.headers }); res.writeHead(200, { 'content-type': 'application/json' }).end('{"stopped":"job"}'); }); let home; let vite; let origin; before(async () => { await new Promise((resolve) => daemon.listen(0, '127.0.0.1', resolve)); home = await mkdtemp(join(tmpdir(), 'albedo-dev-proxy-')); await writeFile(join(home, 'daemon.json'), JSON.stringify({ port: daemon.address().port, token: 'dev-token' })); process.env.ALBEDO_HOME = home; const port = await freePort(); vite = await createServer({ root: web, configFile: join(web, 'vite.config.ts'), logLevel: 'silent', server: { host: '127.0.0.1', port, strictPort: true } }); await vite.listen(); origin = `http://127.0.0.1:${port}`; }); after(async () => { await vite?.close(); daemon.close(); if (home) await rm(home, { recursive: true, force: true }); }); function freePort() { return new Promise((resolve) => { const probe = createHttpServer().listen(0, '127.0.0.1', () => { const { port } = probe.address(); probe.close(() => resolve(port)); }); }); } /** A bodyless POST, the kind a page may send cross-origin without a preflight. */ function stop(headers) { return new Promise((resolve, reject) => { const call = request(`${origin}/api/extensions/run/sessions/s/jobs/j/stop`, { method: 'POST', headers }, (res) => { res.resume(); res.on('end', () => resolve(res.statusCode)); }); call.on('error', reject).end(); }); } for (const foreign of ['null', 'https://evil.example', 'http://127.0.0.1:1']) { test(`a bodyless mutation from Origin ${foreign} never reaches the daemon`, async () => { const before = reached.length; assert.equal(await stop({ origin: foreign }), 403); assert.equal(reached.length, before); }); } test("the dev server's own origin reaches the daemon with the token and without browser headers", async () => { const before = reached.length; assert.equal(await stop({ origin, cookie: 'albedo_prefs=x', referer: `${origin}/` }), 200); const [forwarded] = reached.slice(before); assert.equal(forwarded.url, '/extensions/run/sessions/s/jobs/j/stop'); assert.equal(forwarded.headers.authorization, 'Bearer dev-token'); assert.deepEqual([forwarded.headers.origin, forwarded.headers.cookie, forwarded.headers.referer], [undefined, undefined, undefined]); }); test('a request without Origin, as a same-origin GET or a tool sends, is forwarded', async () => { const before = reached.length; assert.equal(await stop({}), 200); assert.equal(reached.length, before + 1); });