[CSP] createCache nonce-value added to Cache not applied to inline-styles
Open
@mnajdova is already working on this.
Since Sep 14, 2023.
scope: styles
- Dominant language
- JavaScript
- Stars
- 99.1k
- Forks
- 32.5k
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 106
Description
Steps to reproduce 🕹
we are using remixjs+MUI and want to add CSP-Headers following these guides:
CSP-guide
remix-Styling
we added the nonce-value to the cache on CreateEmotionCache.tsx:
CreateEmotionCache.tsx
import createCache from '@emotion/cache';
import { cspScriptNonce } from '@/root';
export default function createEmotionCache() {
return createCache({ key: 'css', nonce: cspScriptNonce });
}
here is how we have entry.server.tsx:
entry.server.tsx
import { CacheProvider } from '@emotion/react';
import createEmotionServer from '@emotion/server/create-instance';
import CssBaseline from '@mui/material/CssBaseline';
import { ThemeProvider } from '@mui/material/styles';
import type { EntryContext } from '@remix-run/node';
import { Response } from '@remix-run/node';
import { RemixServer } from '@remix-run/react';
import { renderToString } from 'react-dom/server';
import { theme } from '@/styles/theme';
import createEmotionCache from '@/styles/utils/createEmotionCache';
import { StateManagerProvider } from '@/lib/state-manager';
export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
): Response {
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);
const html = renderToString(
<StateManagerProvider>
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>
<CssBaseline />
<RemixServer context={remixContext} url={request.url} />
</ThemeProvider>
</CacheProvider>
</StateManagerProvider>,
);
const { styles } = extractCriticalToChunks(html);
const loaderData = remixContext.staticHandlerContext.loaderData as {
root: {
cspScriptNonce: string | undefined;
};
};
const nonce = loaderData.root.cspScriptNonce;
let stylesHTML = '';
styles.forEach(({ key, ids, css }) => {
const emotionKey = `${key} ${ids.join(' ')}`;
const newStyleTag = `<style nonce="${nonce}" data-emotion="${emotionKey}">${css}</style>`;
stylesHTML = `${stylesHTML}${newStyleTag}`;
});
const markup = html.replace(
/<meta(\s)*name="emotion-insertion-point"(\s)*content="emotion-insertion-point"(\s)*\/>/,
`<meta name="emotion-insertion-point" content="emotion-insertion-point"/>${stylesHTML}`,
);
const { CSPolicy, CSPheaders } = createCSP(nonce!!);
responseHeaders.set(CSPolicy, CSPheaders);
responseHeaders.set('Content-Type', 'text/html');
return new Response(`<!DOCTYPE html>${markup}`, {
headers: responseHeaders,
status: responseStatusCode,
});
}
const createCSP = (nonce: string) => {
const isDevelopment = process.env.NODE_ENV === 'development';
let scriptSrc: string;
if (typeof nonce === 'string' && nonce.length > 10) {
scriptSrc = `'report-sample' 'nonce-${nonce}'`;
} else if (isDevelopment) {
// Allow the <LiveReload /> component to load without a nonce in the error pages
scriptSrc = "'report-sample' 'unsafe-inline'";
} else {
scriptSrc = "'report-sample'";
}
const connectSrc = isDevelopment ? 'ws://localhost:*' : '';
const CSPolicy = isDevelopment
? 'Content-Security-Policy-Report-Only'
: 'Content-Security-Policy';
const CSPheaders =
"default-src 'self'; " +
`script-src 'self' ${scriptSrc}; ` +
`style-src 'self' ${scriptSrc}; ` +
"img-src 'self' data: blob:; " +
`connect-src 'self' ${connectSrc} data:; ` +
"object-src 'none'; " +
"worker-src 'self' blob:; " +
"frame-ancestors 'none'; " +
'block-all-mixed-content; ' +
'report-to /reporting/csp';
return { CSPolicy, CSPheaders };
};
Current behavior 😯
we added nonce-value to the <style/> tag in the entry.server.tsx but we are facing the errors:
Expected behavior 🤔
nonce-value assigned to Cache added to <Style/> tags so that they are identified and nonce-values match
Context 🔦
we want to add CSP headers to harden security to our Remixjs app.
Your environment 🌎
`npx @mui/envinfo`
Chrome, Safari, Firefox
System:
OS: macOS 13.5.2
Binaries:
Node: 18.16.1 - /usr/local/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 9.6.6 - /opt/homebrew/bin/npm
Browsers:
Chrome: 116.0.5845.187
Edge: Not Found
Safari: 16.6
npmPackages:
@emotion/react: 11.11.1 => 11.11.1
@emotion/styled: 11.11.0 => 11.11.0
@mui/base: 5.0.0-beta.14 => 5.0.0-beta.14
@mui/core-downloads-tracker: 5.14.8
@mui/material: 5.14.8 => 5.14.8
@mui/private-theming: 5.14.8
@mui/styled-engine: 5.14.8
@mui/system: 5.14.8 => 5.14.8
@mui/types: 7.2.4
@mui/utils: 5.14.8
@mui/x-data-grid: 6.13.0
@mui/x-data-grid-pro: 6.13.0 => 6.13.0
@mui/x-license-pro: 6.10.2 => 6.10.2
@types/react: 18.2.21 => 18.2.21
react: 18.2.0 => 18.2.0
react-dom: 18.2.0 => 18.2.0
typescript: 5.2.2 => 5.2.2
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.