diff --git a/apps/daemon/src/server.ts b/apps/daemon/src/server.ts index 8f22e43e39..e9bb84f2a0 100644 --- a/apps/daemon/src/server.ts +++ b/apps/daemon/src/server.ts @@ -4755,7 +4755,7 @@ export async function startServer({ // Routes that serve content to sandboxed iframes (Origin: null) for // read-only purposes. All other /api routes reject Origin: null. const _NULL_ORIGIN_SAFE_GET_RE = - /^\/projects\/[^/]+\/(?:raw|preview)\/|^\/codex-pets\/[^/]+\/spritesheet$/; + /^\/projects\/[^/]+\/(?:raw|preview)\/|^\/codex-pets\/[^/]+\/spritesheet$|^\/asset-cache$/; // Reject cross-origin requests to API endpoints. // Health/version remain open for monitoring probes. diff --git a/apps/daemon/tests/origin-validation.test.ts b/apps/daemon/tests/origin-validation.test.ts index b98bfeb927..5cb72d69a6 100644 --- a/apps/daemon/tests/origin-validation.test.ts +++ b/apps/daemon/tests/origin-validation.test.ts @@ -43,7 +43,7 @@ function closeServer(server: http.Server): Promise { function createOriginMiddleware(resolvedPort: number, host = '127.0.0.1') { const _NULL_ORIGIN_SAFE_GET_RE = - /^\/projects\/[^/]+\/raw\/|^\/codex-pets\/[^/]+\/spritesheet$/; + /^\/projects\/[^/]+\/(?:raw|preview)\/|^\/codex-pets\/[^/]+\/spritesheet$|^\/asset-cache$/; return (req: Request, res: Response, next: NextFunction) => { const origin = req.headers.origin; if (origin == null || origin === '') return next(); @@ -95,6 +95,9 @@ function makeTestApp(port: number, host = '127.0.0.1') { } res.type('image/png').send(Buffer.from('fake-sprite')); }); + app.get('/api/asset-cache', (_req, res) => { + res.type('image/png').send(Buffer.from('fake-asset')); + }); return app; } @@ -326,6 +329,13 @@ describe('daemon origin validation middleware', () => { expect(res.headers['access-control-allow-origin']).toBe('null'); }); + it('allows Origin: null for GET asset-cache routes', async () => { + const res = await request(port, 'GET', '/api/asset-cache?url=https%3A%2F%2Fcdn.example.com%2Fhero.webp', { + origin: 'null', + }); + expect(res.status).toBe(200); + }); + it('rejects Origin: null on POST to state-changing endpoints', async () => { const res = await request(port, 'POST', '/api/projects', { origin: 'null',