diff --git a/server/src/app.ts b/server/src/app.ts index 73cf701..35a0d9c 100644 --- a/server/src/app.ts +++ b/server/src/app.ts @@ -53,7 +53,16 @@ app.use('*', async (c, next) => { }) // Security headers: X-Frame-Options, X-Content-Type-Options, HSTS, Referrer-Policy, etc. +// ARCHY_EMBEDDED=1 means this instance is running as an app inside the +// Archipelago node dashboard's iframe (a first-party, trusted embedding +// context on the same host, different port — never a third-party site). +// X-Frame-Options: SAMEORIGIN (the secureHeaders default) blocks that framing +// outright, since the dashboard and this app are different origins by port. +// Standalone/public-arena instances (ARCHY_EMBEDDED unset) keep the default +// clickjacking protection. +const isEmbedded = process.env.ARCHY_EMBEDDED === '1' app.use('*', secureHeaders({ + xFrameOptions: isEmbedded ? false : true, contentSecurityPolicy: process.env.NODE_ENV === 'production' ? { defaultSrc: ["'self'"], scriptSrc: ["'self'", 'blob:', "'wasm-unsafe-eval'"],