Files
gitmost/apps/server/src/common/helpers/security-headers.spec.ts
T
claude_code f8e8ada581 test(server): add behavioural unit tests for auth + common security helpers
Batch 1 of the test-strategy rollout. Fills the highest-value gaps where
existing specs were only `toBeDefined()` smoke tests or absent. Test-only,
no production source touched.

- token.service.behavior.spec.ts: verifyJwt type-mismatch rejection (confused
  deputy), generateAccessToken/generateCollabToken disabled-user -> Forbidden,
  agent `actor` claim only from signed provenance, correct expiry.
- auth.util.spec.ts: computeEmailSignature (stable HMAC, case-normalized),
  throwIfEmailNotVerified, validateSsoEnforcement, validateAllowedEmail;
  it.todo flags the unguarded `@`-less email TypeError.
- guards/setup.guard.spec.ts: cloud blocks setup, first-run allows, re-run on
  an initialised instance is forbidden (privilege escalation guard).
- security-headers.spec.ts: resolveFrameHeader clickjacking/CSP branches.
- utils.security.spec.ts: redactSensitiveUrl, extractBearerTokenFromHeader,
  parseRedisUrl, normalizePostgresUrl, diffAuditTrackedFields, isUserDisabled.

60 tests + 1 todo, all green. Reviewed for mutation resistance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:00:09 +03:00

53 lines
1.7 KiB
TypeScript

import { resolveFrameHeader } from './security-headers';
describe('resolveFrameHeader', () => {
describe('iframe embedding disabled (clickjacking protection)', () => {
it('returns X-Frame-Options SAMEORIGIN and ignores origins', () => {
expect(resolveFrameHeader(false, [])).toEqual({
name: 'X-Frame-Options',
value: 'SAMEORIGIN',
});
});
it('still returns X-Frame-Options even when origins are configured', () => {
// A wrong branch could leak a permissive CSP here; origins must be ignored
// when embedding is disabled so clickjacking protection stays intact.
const result = resolveFrameHeader(false, [
'https://a.com',
'https://b.com',
]);
expect(result).toEqual({
name: 'X-Frame-Options',
value: 'SAMEORIGIN',
});
expect(result?.name).not.toBe('Content-Security-Policy');
});
});
describe('iframe embedding allowed', () => {
it('returns null when there are no allowed origins', () => {
expect(resolveFrameHeader(true, [])).toBeNull();
});
it('builds a frame-ancestors CSP for a single origin', () => {
expect(resolveFrameHeader(true, ['https://a.com'])).toEqual({
name: 'Content-Security-Policy',
value: "frame-ancestors 'self' https://a.com",
});
});
it('space-joins multiple origins after self', () => {
expect(
resolveFrameHeader(true, [
'https://a.com',
'https://b.com',
'https://c.com',
]),
).toEqual({
name: 'Content-Security-Policy',
value: "frame-ancestors 'self' https://a.com https://b.com https://c.com",
});
});
});
});