diff --git a/lib/__tests__/plugin-sandbox-route-gate.test.ts b/lib/__tests__/plugin-sandbox-route-gate.test.ts index 6032ca8e0..4da191ba2 100644 --- a/lib/__tests__/plugin-sandbox-route-gate.test.ts +++ b/lib/__tests__/plugin-sandbox-route-gate.test.ts @@ -113,6 +113,8 @@ describe('plugin sandbox routes (GHSA-96cx-gx36-3g79)', () => { } // The router refetches the sandbox page itself, so its own origin stays. expect(directives['connect-src']).toEqual(["'self'"]); + // Plugin frames may use forms (allow-forms) but not post them anywhere. + expect(directives['form-action']).toEqual(["'none'"]); }); it('keeps https images and connections for the mail UI itself', async () => { diff --git a/lib/plugin-sandbox/host-bridge.ts b/lib/plugin-sandbox/host-bridge.ts index 6bd6704be..315d89652 100644 --- a/lib/plugin-sandbox/host-bridge.ts +++ b/lib/plugin-sandbox/host-bridge.ts @@ -161,7 +161,9 @@ export class SandboxInstance { // `sandbox-ready` would never post). const sandboxFlags = this.privileged || process.env.NODE_ENV === 'development' ? 'allow-scripts allow-same-origin' - : 'allow-scripts'; + // allow-forms: plugin UIs can use
and get its submit event. The + // sandbox CSP sets form-action 'none', so a form can't post anywhere. + : 'allow-scripts allow-forms'; if (!this.privileged && process.env.NODE_ENV === 'development') warnDevSandboxOnce(); this.iframe.setAttribute('sandbox', sandboxFlags); this.iframe.setAttribute('referrerpolicy', 'no-referrer'); diff --git a/proxy.ts b/proxy.ts index c5666892b..f00047d52 100644 --- a/proxy.ts +++ b/proxy.ts @@ -336,7 +336,9 @@ export async function proxy(request: NextRequest) { frameSrc, `object-src 'self' blob:`, `base-uri 'self'`, - `form-action ${["'self'", ...wopiOrigins].join(" ")}`, + // Plugin frames may use for its submit event (allow-forms), but a + // form must not post anywhere: that would be a way out past connect-src. + isSandboxPath ? `form-action 'none'` : `form-action ${["'self'", ...wopiOrigins].join(" ")}`, `frame-ancestors ${frameAncestors}`, `media-src 'self' blob:`, ].join("; ");