fix: Allow service worker to load on custom domains (#12502)

* fix: Allow service worker to load on custom domains

Add explicit worker-src 'self' so the service worker can register on
team custom domains. Without it, browsers fall back to script-src which
only lists env.URL and env.CDN_URL, blocking /static/sw.js on hosts
like docs.getoutline.com.

* fix: Switch worker-src approach to script-src 'self' for type safety

The @types/koa-helmet definitions don't include workerSrc. Add 'self'
to script-src instead — worker-src falls back to script-src per spec,
and 'self' matches the document origin on custom domains.

* fix: Properly add worker-src directive without script-src widening

Extract the CSP directives to a local variable so workerSrc can be
included despite koa-helmet's outdated type definitions missing it
(the underlying helmet supports it). Also drop @types/koa-helmet
since the package now ships its own (equivalent) types.
This commit is contained in:
Tom Moor
2026-05-28 09:07:05 -04:00
committed by GitHub
parent d2a0bf9923
commit ae5cd6a159
3 changed files with 27 additions and 35 deletions
-1
View File
@@ -307,7 +307,6 @@
"@types/katex": "^0.16.8", "@types/katex": "^0.16.8",
"@types/koa": "^2.15.1", "@types/koa": "^2.15.1",
"@types/koa-compress": "^4.0.7", "@types/koa-compress": "^4.0.7",
"@types/koa-helmet": "^6.0.8",
"@types/koa-logger": "^3.1.5", "@types/koa-logger": "^3.1.5",
"@types/koa-mount": "^4.0.5", "@types/koa-mount": "^4.0.5",
"@types/koa-router": "^7.4.9", "@types/koa-router": "^7.4.9",
+26 -21
View File
@@ -84,26 +84,31 @@ export default function createCSPMiddleware(options?: CSPOptions) {
return function cspMiddleware(ctx: Context, next: Next) { return function cspMiddleware(ctx: Context, next: Next) {
ctx.state.cspNonce = crypto.randomBytes(16).toString("hex"); ctx.state.cspNonce = crypto.randomBytes(16).toString("hex");
return contentSecurityPolicy({ // Note: workerSrc is included even though it's missing from the koa-helmet
directives: { // type definitions — the underlying helmet supports it. The service worker
baseUri: ["'none'"], // is served from the same origin as the document, which may be a custom
defaultSrc, // domain that is not present in scriptSrc.
styleSrc, const directives = {
scriptSrc: [ baseUri: ["'none'"],
...uniq(scriptSrc), defaultSrc,
...(options?.extraScriptSrc ?? []), styleSrc,
env.DEVELOPMENT_UNSAFE_INLINE_CSP scriptSrc: [
? "'unsafe-inline'" ...uniq(scriptSrc),
: `'nonce-${ctx.state.cspNonce}'`, ...(options?.extraScriptSrc ?? []),
], env.DEVELOPMENT_UNSAFE_INLINE_CSP
mediaSrc: ["*", "data:", "blob:"], ? "'unsafe-inline'"
imgSrc: ["*", "data:", "blob:"], : `'nonce-${ctx.state.cspNonce}'`,
frameSrc: ["*", "data:"], ],
objectSrc, mediaSrc: ["*", "data:", "blob:"],
// Do not use connect-src: because self + websockets does not work in imgSrc: ["*", "data:", "blob:"],
// Safari, ref: https://bugs.webkit.org/show_bug.cgi?id=201591 frameSrc: ["*", "data:"],
connectSrc: ["*"], workerSrc: ["'self'"],
}, objectSrc,
})(ctx, next); // Do not use connect-src: because self + websockets does not work in
// Safari, ref: https://bugs.webkit.org/show_bug.cgi?id=201591
connectSrc: ["*"],
};
return contentSecurityPolicy({ directives })(ctx, next);
}; };
} }
+1 -13
View File
@@ -6919,17 +6919,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/koa-helmet@npm:^6.0.8":
version: 6.0.8
resolution: "@types/koa-helmet@npm:6.0.8"
dependencies:
"@types/koa": "npm:*"
"@types/node": "npm:*"
helmet: "npm:^4.0.0"
checksum: 10c0/73c2ad0b37561b399e9493cf5ca2dccc0e37c3ea5da3cd281685728a242bc63f1b83d77838ff2ec616fad023e79c0f3a74ca935c740c4cc3c63a1fed3c27fe84
languageName: node
linkType: hard
"@types/koa-logger@npm:^3.1.5": "@types/koa-logger@npm:^3.1.5":
version: 3.1.5 version: 3.1.5
resolution: "@types/koa-logger@npm:3.1.5" resolution: "@types/koa-logger@npm:3.1.5"
@@ -11869,7 +11858,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"helmet@npm:^4.0.0, helmet@npm:^4.4.1": "helmet@npm:^4.4.1":
version: 4.6.0 version: 4.6.0
resolution: "helmet@npm:4.6.0" resolution: "helmet@npm:4.6.0"
checksum: 10c0/fe0d986fc465be0f652e67dd1feab576d9b08b797846fdac5719d5ca857977d6b1712327223a7c25695104dfde118fdf303f4a18efca7cddf0159821bf36b7f8 checksum: 10c0/fe0d986fc465be0f652e67dd1feab576d9b08b797846fdac5719d5ca857977d6b1712327223a7c25695104dfde118fdf303f4a18efca7cddf0159821bf36b7f8
@@ -15132,7 +15121,6 @@ __metadata:
"@types/katex": "npm:^0.16.8" "@types/katex": "npm:^0.16.8"
"@types/koa": "npm:^2.15.1" "@types/koa": "npm:^2.15.1"
"@types/koa-compress": "npm:^4.0.7" "@types/koa-compress": "npm:^4.0.7"
"@types/koa-helmet": "npm:^6.0.8"
"@types/koa-logger": "npm:^3.1.5" "@types/koa-logger": "npm:^3.1.5"
"@types/koa-mount": "npm:^4.0.5" "@types/koa-mount": "npm:^4.0.5"
"@types/koa-router": "npm:^7.4.9" "@types/koa-router": "npm:^7.4.9"