fix: remove nonce from <link> tags — breaks CSS on mobile/caching proxies
All checks were successful
Build and Push Docker Image / build (push) Successful in 22s
CI / Security audit (push) Successful in 49s
CI / Tests & coverage (push) Successful in 1m4s

style-src 'self' already permits same-origin stylesheets without a nonce.
Injecting a nonce onto <link rel=stylesheet> causes silent CSS failure on
mobile Safari and any setup where a caching proxy serves stale HTML (the
nonce in the HTML no longer matches the per-request CSP header nonce).

Nonce injection is now limited to <script> tags only, where it is
actually required to permit the same-origin app.js.
This commit is contained in:
2026-05-17 09:28:44 +01:00
parent c86694fc8f
commit 3c3382401c

View File

@@ -214,15 +214,17 @@ app.use(express.static(PUBLIC_DIR, {
}
}));
// Serve index.html with nonce injected into the <script> and <link> tags
// Serve index.html with CSP nonce injected into <script> tags
function serveIndex(req, res) {
fs.readFile(INDEX_HTML, 'utf8', (err, html) => {
if (err) return res.status(500).send('Internal Server Error');
const nonce = res.locals.cspNonce;
// Inject nonce into <script> and <link rel="stylesheet"> tags
// Only inject nonce into <script> tags — style-src 'self' already permits
// same-origin <link rel=stylesheet> without a nonce, and injecting a nonce
// onto <link> breaks mobile browsers / caching proxies (stale HTML carries
// the old nonce which no longer matches the per-request CSP header).
const patched = html
.replace(/<script([^>]*)>/gi, `<script nonce="${nonce}"$1>`)
.replace(/<link([^>]*rel=["']stylesheet["'][^>]*)>/gi, `<link nonce="${nonce}"$1>`);
.replace(/<script([^>]*)>/gi, `<script nonce="${nonce}"$1>`);
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.send(patched);
});