mirror of
https://github.com/HeyPuter/puter.git
synced 2026-08-23 22:47:19 +00:00
Let a browser send the device fingerprint header it is offered
`fingerprint.ts` reads the device fingerprint from a request body or, for authenticated requests with no body to carry it, from `x-puter-device-fingerprint`. That header is documented there as "the header the GUI may send the device fingerprint on for non-signup requests", and the middleware has always honoured it. A browser could never actually send it. The CORS allowlist in `#installCors` does not include it, so the preflight comes back without it in `Access-Control-Allow-Headers`, the browser abandons the request, and `fetch` rejects before anything reaches the server. Nothing in tree sends the header today, which is why this went unnoticed: the first client to try it sees every call fail with a network error rather than a readable status. Adds the header to the allowlist, and a preflight test asserting the browser is allowed to ask for it.
This commit is contained in:
@@ -272,6 +272,29 @@ describe('PuterServer host header validation', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('lets a cross-origin preflight ask for the device fingerprint header', async () => {
|
||||
// `fingerprint.ts` reads the device fingerprint off
|
||||
// `x-puter-device-fingerprint` for authenticated requests with no body
|
||||
// to carry it. That channel only exists if the preflight admits the
|
||||
// header: a browser abandons the request otherwise, and the call never
|
||||
// leaves it.
|
||||
const res = await request(
|
||||
'/healthcheck',
|
||||
{
|
||||
host: `api.puter.localhost:${port}`,
|
||||
origin: 'http://puter.localhost',
|
||||
'access-control-request-method': 'GET',
|
||||
'access-control-request-headers':
|
||||
'authorization,x-puter-device-fingerprint',
|
||||
},
|
||||
'OPTIONS',
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
expect(
|
||||
String(res.headers['access-control-allow-headers']).toLowerCase(),
|
||||
).toContain('x-puter-device-fingerprint');
|
||||
});
|
||||
|
||||
it('still short-circuits OPTIONS preflight off the dav subdomain', async () => {
|
||||
const res = await request(
|
||||
'/some-path',
|
||||
|
||||
@@ -685,6 +685,12 @@ export class PuterServer {
|
||||
'X-Expected-Entity-Length',
|
||||
'DAV',
|
||||
'stripe-signature',
|
||||
// The GUI's fallback channel for the device fingerprint on
|
||||
// authenticated requests that have no body to carry it (see
|
||||
// core/http/middleware/fingerprint.ts). Without it here the
|
||||
// preflight refuses the header and the request never leaves the
|
||||
// browser.
|
||||
'x-puter-device-fingerprint',
|
||||
].join(', ');
|
||||
|
||||
// What a browser DAV client is allowed to read back off a response.
|
||||
|
||||
Reference in New Issue
Block a user