fix(security): allow same-origin iframes via CSP frame-src 'self' (#1579)#1580
Conversation
) The auto-itemize PDF viewer embeds the uploaded PDF in an <iframe> so users can review the document alongside the extracted line items. When Helmet's Content Security Policy was applied, the `frame-src` directive defaulted to `'none'`, which caused the browser to block the blob: URL used as the iframe src and silently prevented the PDF from rendering. ## Changes - **helmetPlugin.ts**: Add `frameSrc: ["'self'"]` to the `contentSecurityPolicy` directives object. The `frame-src` directive controls which URLs may be loaded as nested browsing contexts (iframes, frames). Setting it to `'self'` permits same-origin iframes (including blob: URLs created by the same origin) while still blocking any cross-origin iframe embedding attempts. Note: `frame-src` (what *this* page may embed) is distinct from the `X-Frame-Options: DENY` header (whether *other* pages may embed this app). Both directives are applied — Helmet's `frameguard` keeps `X-Frame-Options: DENY` unchanged, preventing Cornerstone itself from being framed by third-party sites. ## Tests - **helmetPlugin.test.ts**: New assertion verifies that the CSP `Content-Security-Policy` response header includes `frame-src 'self'`, confirming the directive is emitted correctly in all responses. - **invoice-auto-itemize-page.spec.ts**: New E2E test coverage for the auto-itemize PDF page, including smoke test that the page loads, the PDF iframe is visible after file upload, and extracted line items are rendered. Tests run across desktop, tablet, and mobile viewports. Fixes #1579 Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com>
|
[security-engineer] APPROVED. Security Review — CSP
|
|
🎉 This PR is included in version 2.7.0-beta.15 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
frame-srcdefaulting to'none'; PDF would silently fail to render in the viewerframeSrc: ["'self'"]tohelmetPlugin.tsto permit same-origin (and blob:) iframes without loosening cross-origin embedding restrictionsX-Frame-Options: DENY(via Helmet'sframeguard) is preserved unchanged — Cornerstone itself cannot be framed by third-party sitesFixes #1579
Test plan
helmetPlugin.test.tsassertsContent-Security-Policyheader includesframe-src 'self'invoice-auto-itemize-page.spec.tscovers page load, PDF iframe visibility after upload, and extracted line items — runs across desktop, tablet, and mobile viewportsDocker preview image
A preview image will be published to DockerHub once CI passes:
steilerdev/cornerstone:pr-<PR_NUMBER>Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) noreply@anthropic.com