diff --git a/README.md b/README.md index 57e0b8e1a..55e6215f4 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Serves at [`http://localhost:6415`](http://localhost:6415) ```sh docker build -t litdev . --build-arg PLAYGROUND_SANDBOX=http://localhost:7416/ -docker run --rm --name litdev -p 7415:7415 -e PORT=7415 -e MODE=main litdev +docker run --rm --name litdev -p 7415:7415 -e PORT=7415 -e MODE=main -e PLAYGROUND_SANDBOX=http://localhost:7416/ litdev docker run --rm --name litdev-playground -p 7416:7416 -e PORT=7416 -e MODE=playground litdev ``` diff --git a/cloudbuild-main.yaml b/cloudbuild-main.yaml index 1d275df00..071cd7c78 100644 --- a/cloudbuild-main.yaml +++ b/cloudbuild-main.yaml @@ -46,7 +46,7 @@ steps: - '--min-instances=1' - '--max-instances=1000' # Serve the main site - - '--update-env-vars=MODE=main,REPORT_CSP_VIOLATIONS=true' + - '--update-env-vars=MODE=main,REPORT_CSP_VIOLATIONS=true,PLAYGROUND_SANDBOX=https://playground.lit.dev/' # Create a new Cloud Run revision for the Playground sandbox. # diff --git a/cloudbuild-pr.yaml b/cloudbuild-pr.yaml index 62d68fe0e..2bb911d83 100644 --- a/cloudbuild-pr.yaml +++ b/cloudbuild-pr.yaml @@ -49,7 +49,7 @@ steps: - '--min-instances=0' - '--max-instances=1' # Serve the main site - - '--update-env-vars=MODE=main' + - '--update-env-vars=MODE=main,PLAYGROUND_SANDBOX=https://pr$_PR_NUMBER-$SHORT_SHA---lit-dev-playground-5ftespv5na-uc.a.run.app/' # Create a new Cloud Run revision for the playground sandbox. # diff --git a/packages/lit-dev-server/package.json b/packages/lit-dev-server/package.json index c18f17cb3..6ae239e03 100644 --- a/packages/lit-dev-server/package.json +++ b/packages/lit-dev-server/package.json @@ -11,7 +11,7 @@ "build": "npm run build:ts", "build:ts": "../../node_modules/.bin/tsc", "start": "run-p start:main start:playground", - "start:main": "MODE=main PORT=6415 node lib/server.js", + "start:main": "MODE=main PORT=6415 PLAYGROUND_SANDBOX=http://localhost:6416 node lib/server.js", "start:playground": "MODE=playground PORT=6416 node lib/server.js", "format": "../../node_modules/.bin/prettier \"**/*.{ts,js,json,html,css,md}\" --write" }, diff --git a/packages/lit-dev-server/src/middleware/content-security-policy-middleware.ts b/packages/lit-dev-server/src/middleware/content-security-policy-middleware.ts index b8863c27b..98bfc15e4 100644 --- a/packages/lit-dev-server/src/middleware/content-security-policy-middleware.ts +++ b/packages/lit-dev-server/src/middleware/content-security-policy-middleware.ts @@ -26,6 +26,11 @@ export interface ContentSecurityPolicyMiddlewareOptions { * allowlisted to run as inline scripts. */ inlineScriptHashes?: string[]; + + /** + * Origin for Playground preview iframes. + */ + playgroundPreviewOrigin: string; } /** @@ -39,7 +44,7 @@ export interface ContentSecurityPolicyMiddlewareOptions { * https://speakerdeck.com/lweichselbaum/csp-a-successful-mess-between-hardening-and-mitigation */ export const contentSecurityPolicyMiddleware = ( - opts: ContentSecurityPolicyMiddlewareOptions = {} + opts: ContentSecurityPolicyMiddlewareOptions ): Koa.Middleware => { const cspHeaderValue = [ // TODO(aomarks) We should also enable trusted types, but that will require @@ -71,13 +76,8 @@ export const contentSecurityPolicyMiddleware = ( // them for automatic reloads. `connect-src 'self' https://unpkg.com/${opts.devMode ? ` ws:` : ''}`, - // TODO(aomarks) These frame-src directives are only needed for embedding - // Playground previews. We can know the exact origin that is being used for - // Playground previews, so we could restrict this further by passing that in - // as a parameter to the middleware. - // - // In dev mode, http: is needed for http://localhost Playground iframes. - `frame-src https:${opts.devMode ? ' http:' : ''}`, + // Playground previews and embedded YouTube videos. + `frame-src ${opts.playgroundPreviewOrigin} https://www.youtube-nocookie.com/`, // We need 'unsafe-inline' because CodeMirror uses inline styles See // https://discuss.codemirror.net/t/inline-styles-and-content-security-policy/1311/2 diff --git a/packages/lit-dev-server/src/server.ts b/packages/lit-dev-server/src/server.ts index 3a3062e90..d487f8f20 100644 --- a/packages/lit-dev-server/src/server.ts +++ b/packages/lit-dev-server/src/server.ts @@ -50,9 +50,14 @@ if (mode === 'playground') { ) .trim() .split('\n'); + const playgroundPreviewOrigin = process.env.PLAYGROUND_SANDBOX; + if (!playgroundPreviewOrigin) { + throw new Error('PLAYGROUND_SANDBOX env was not set'); + } app.use( contentSecurityPolicyMiddleware({ inlineScriptHashes, + playgroundPreviewOrigin, reportViolations: process.env.REPORT_CSP_VIOLATIONS === 'true', }) ); diff --git a/packages/lit-dev-tools-esm/src/dev-server.ts b/packages/lit-dev-tools-esm/src/dev-server.ts index a335698ea..e3cead7eb 100644 --- a/packages/lit-dev-tools-esm/src/dev-server.ts +++ b/packages/lit-dev-tools-esm/src/dev-server.ts @@ -79,7 +79,10 @@ startDevServer({ removeWatchScriptFromPlaygroundFiles, ], middleware: [ - contentSecurityPolicyMiddleware({devMode: true}), + contentSecurityPolicyMiddleware({ + devMode: true, + playgroundPreviewOrigin: `http://localhost:${PLAYGROUND_PORT}`, + }), redirectMiddleware(), ], watch: true,