From 4d5f577e837f6f051176694047ea79092b5d7c7b Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sun, 26 Jul 2026 23:07:29 -0400 Subject: [PATCH] fix: replace frame-ancestors instead of merging it Merging the configured value into the default turned a deliberate CSP_FRAME_ANCESTORS='none' into `frame-ancestors 'self' 'none'`, which browsers resolve back to 'self'. Also bail out if the serialized policy somehow lacks the nonce slot rather than emitting a header the shell cannot match. --- packages/api/src/security/csp.spec.ts | 7 +++++++ packages/api/src/security/csp.ts | 27 ++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/api/src/security/csp.spec.ts b/packages/api/src/security/csp.spec.ts index 6a408e5d4f..0c30bdd4ae 100644 --- a/packages/api/src/security/csp.spec.ts +++ b/packages/api/src/security/csp.spec.ts @@ -93,6 +93,13 @@ describe('policy directives', () => { expect(header).toContain("frame-ancestors 'self' https://portal.example.com"); }); + it("replaces rather than merges frame-ancestors, so 'none' is not diluted by 'self'", () => { + const header = headerFor({ CSP_FRAME_ANCESTORS: "'none'" }); + + expect(header).toContain("frame-ancestors 'none'"); + expect(header).not.toContain("frame-ancestors 'self'"); + }); + it('appends additional directives and skips malformed ones', () => { const header = serializeCspDirectives( buildCspDirectives({ diff --git a/packages/api/src/security/csp.ts b/packages/api/src/security/csp.ts index eb4ee78b6e..a00ecd4a76 100644 --- a/packages/api/src/security/csp.ts +++ b/packages/api/src/security/csp.ts @@ -76,7 +76,7 @@ function scriptSources(scriptExtras: string[]): string[] { * `'unsafe-inline'`, which would block every `