Skip to content

Commit 33d328b

Browse files
authored
Constrain frame-src CSP to only allow the playground and youtube embeds (#528)
1 parent a123834 commit 33d328b

File tree

7 files changed

+21
-13
lines changed

7 files changed

+21
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ Serves at [`http://localhost:6415`](http://localhost:6415)
113113

114114
```sh
115115
docker build -t litdev . --build-arg PLAYGROUND_SANDBOX=http://localhost:7416/
116-
docker run --rm --name litdev -p 7415:7415 -e PORT=7415 -e MODE=main litdev
116+
docker run --rm --name litdev -p 7415:7415 -e PORT=7415 -e MODE=main -e PLAYGROUND_SANDBOX=http://localhost:7416/ litdev
117117
docker run --rm --name litdev-playground -p 7416:7416 -e PORT=7416 -e MODE=playground litdev
118118
```
119119

cloudbuild-main.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ steps:
4646
- '--min-instances=1'
4747
- '--max-instances=1000'
4848
# Serve the main site
49-
- '--update-env-vars=MODE=main,REPORT_CSP_VIOLATIONS=true'
49+
- '--update-env-vars=MODE=main,REPORT_CSP_VIOLATIONS=true,PLAYGROUND_SANDBOX=https://playground.lit.dev/'
5050

5151
# Create a new Cloud Run revision for the Playground sandbox.
5252
#

cloudbuild-pr.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ steps:
4949
- '--min-instances=0'
5050
- '--max-instances=1'
5151
# Serve the main site
52-
- '--update-env-vars=MODE=main'
52+
- '--update-env-vars=MODE=main,PLAYGROUND_SANDBOX=https://pr$_PR_NUMBER-$SHORT_SHA---lit-dev-playground-5ftespv5na-uc.a.run.app/'
5353

5454
# Create a new Cloud Run revision for the playground sandbox.
5555
#

packages/lit-dev-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"build": "npm run build:ts",
1212
"build:ts": "../../node_modules/.bin/tsc",
1313
"start": "run-p start:main start:playground",
14-
"start:main": "MODE=main PORT=6415 node lib/server.js",
14+
"start:main": "MODE=main PORT=6415 PLAYGROUND_SANDBOX=http://localhost:6416 node lib/server.js",
1515
"start:playground": "MODE=playground PORT=6416 node lib/server.js",
1616
"format": "../../node_modules/.bin/prettier \"**/*.{ts,js,json,html,css,md}\" --write"
1717
},

packages/lit-dev-server/src/middleware/content-security-policy-middleware.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ export interface ContentSecurityPolicyMiddlewareOptions {
2626
* allowlisted to run as inline scripts.
2727
*/
2828
inlineScriptHashes?: string[];
29+
30+
/**
31+
* Origin for Playground preview iframes.
32+
*/
33+
playgroundPreviewOrigin: string;
2934
}
3035

3136
/**
@@ -39,7 +44,7 @@ export interface ContentSecurityPolicyMiddlewareOptions {
3944
* https://speakerdeck.com/lweichselbaum/csp-a-successful-mess-between-hardening-and-mitigation
4045
*/
4146
export const contentSecurityPolicyMiddleware = (
42-
opts: ContentSecurityPolicyMiddlewareOptions = {}
47+
opts: ContentSecurityPolicyMiddlewareOptions
4348
): Koa.Middleware => {
4449
const cspHeaderValue = [
4550
// TODO(aomarks) We should also enable trusted types, but that will require
@@ -71,13 +76,8 @@ export const contentSecurityPolicyMiddleware = (
7176
// them for automatic reloads.
7277
`connect-src 'self' https://unpkg.com/${opts.devMode ? ` ws:` : ''}`,
7378

74-
// TODO(aomarks) These frame-src directives are only needed for embedding
75-
// Playground previews. We can know the exact origin that is being used for
76-
// Playground previews, so we could restrict this further by passing that in
77-
// as a parameter to the middleware.
78-
//
79-
// In dev mode, http: is needed for http://localhost Playground iframes.
80-
`frame-src https:${opts.devMode ? ' http:' : ''}`,
79+
// Playground previews and embedded YouTube videos.
80+
`frame-src ${opts.playgroundPreviewOrigin} https://www.youtube-nocookie.com/`,
8181

8282
// We need 'unsafe-inline' because CodeMirror uses inline styles See
8383
// https://discuss.codemirror.net/t/inline-styles-and-content-security-policy/1311/2

packages/lit-dev-server/src/server.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,14 @@ if (mode === 'playground') {
5050
)
5151
.trim()
5252
.split('\n');
53+
const playgroundPreviewOrigin = process.env.PLAYGROUND_SANDBOX;
54+
if (!playgroundPreviewOrigin) {
55+
throw new Error('PLAYGROUND_SANDBOX env was not set');
56+
}
5357
app.use(
5458
contentSecurityPolicyMiddleware({
5559
inlineScriptHashes,
60+
playgroundPreviewOrigin,
5661
reportViolations: process.env.REPORT_CSP_VIOLATIONS === 'true',
5762
})
5863
);

packages/lit-dev-tools-esm/src/dev-server.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ startDevServer({
7979
removeWatchScriptFromPlaygroundFiles,
8080
],
8181
middleware: [
82-
contentSecurityPolicyMiddleware({devMode: true}),
82+
contentSecurityPolicyMiddleware({
83+
devMode: true,
84+
playgroundPreviewOrigin: `http://localhost:${PLAYGROUND_PORT}`,
85+
}),
8386
redirectMiddleware(),
8487
],
8588
watch: true,

0 commit comments

Comments
 (0)