import { INestApplication } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import request from 'supertest'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { AppModule } from '../app.module'; // Boots the AppModule without a database (like health.e2e.test.ts): the // middleware under test runs before any route logic, so the always-on // healthz endpoint is a representative response (issue #197). describe('security response headers & CORS (e2e, issue #197)', () => { let app: INestApplication; const appOrigin = 'http://localhost:5173'; // APP_BASE_URL default origin beforeAll(async () => { process.env.NODE_ENV = 'test'; process.env.DATABASE_URL ??= 'postgresql://nobody:nothing@127.0.0.1:59999/absent'; const moduleRef = await Test.createTestingModule({ imports: [AppModule] }).compile(); app = moduleRef.createNestApplication(); app.setGlobalPrefix('api/v1'); await app.init(); }); afterAll(async () => { await app.close(); }); it('stamps the full header set on a representative response', async () => { const res = await request(app.getHttpServer()).get('/api/v1/healthz').expect(200); expect(res.headers['strict-transport-security']).toBe('max-age=31536000'); expect(res.headers['x-content-type-options']).toBe('nosniff'); expect(res.headers['referrer-policy']).toBe('no-referrer'); // SAMEORIGIN, not DENY — the plugin sandbox frame is embedded // same-origin (plugins.e2e.db.test.ts asserts the frame side). expect(res.headers['x-frame-options']).toBe('SAMEORIGIN'); expect(res.headers['permissions-policy']).toBe( 'camera=(), microphone=(), geolocation=(), payment=(), usb=()', ); }); it('stamps the headers on error responses too (unknown route)', async () => { const res = await request(app.getHttpServer()).get('/api/v1/does-not-exist').expect(404); expect(res.headers['x-content-type-options']).toBe('nosniff'); expect(res.headers['x-frame-options']).toBe('SAMEORIGIN'); }); it('grants a foreign origin nothing (no ACAO), while varying on Origin', async () => { const res = await request(app.getHttpServer()) .get('/api/v1/healthz') .set('Origin', 'https://attacker.example') .expect(200); expect(res.headers['access-control-allow-origin']).toBeUndefined(); expect(res.headers['access-control-allow-credentials']).toBeUndefined(); expect(res.headers.vary).toContain('Origin'); }); it("echoes only the app's own origin, with the credentials rule stated", async () => { const res = await request(app.getHttpServer()) .get('/api/v1/healthz') .set('Origin', appOrigin) .expect(200); expect(res.headers['access-control-allow-origin']).toBe(appOrigin); expect(res.headers['access-control-allow-credentials']).toBe('true'); }); it('leaves a foreign preflight ungranted (no CORS response headers)', async () => { const res = await request(app.getHttpServer()) .options('/api/v1/healthz') .set('Origin', 'https://attacker.example') .set('Access-Control-Request-Method', 'POST'); expect(res.headers['access-control-allow-origin']).toBeUndefined(); expect(res.headers['access-control-allow-methods']).toBeUndefined(); }); });