create Content Security Policyutility
utility
Create a content security policy to secure your application. The default content security policy includes exclusions for cdn.shopify.com and a script nonce.
- Anchor to propsprops&
- headerstring
The content security policy header
- noncestring
A randomly generated nonce string that should be passed to any custom
script
element- NonceProviderComponentType<{children: ReactNode}>
ContentSecurityPolicy
CreateContentSecurityPolicyGeneratedType
- props
CreateContentSecurityPolicy & ShopProp
ContentSecurityPolicy
export function createContentSecurityPolicy(
props?: CreateContentSecurityPolicy & ShopProp,
): ContentSecurityPolicy {
const nonce = generateNonce();
const header = createCSPHeader(nonce, props);
const Provider = ({children}: {children: ReactNode}) => {
return createElement(NonceProvider, {value: nonce}, children);
};
return {
nonce,
header,
NonceProvider: Provider,
};
}
CreateContentSecurityPolicy
- baseUri
DirectiveValues
- blockAllMixedContent
boolean
- childSrc
DirectiveValues
- connectSrc
DirectiveValues
- defaultSrc
DirectiveValues
- fontSrc
DirectiveValues
- formAction
DirectiveValues
- frameAncestors
DirectiveValues
- frameSrc
DirectiveValues
- imgSrc
DirectiveValues
- manifestSrc
DirectiveValues
- mediaSrc
DirectiveValues
- navigateTo
DirectiveValues
- objectSrc
DirectiveValues
- pluginTypes
DirectiveValues
- prefetchSrc
DirectiveValues
- reportTo
DirectiveValues
- reportUri
DirectiveValues
- sandbox
DirectiveValues
- scriptSrc
DirectiveValues
- scriptSrcElem
DirectiveValues
- styleSrc
DirectiveValues
- upgradeInsecureRequests
boolean
- workerSrc
DirectiveValues
{
defaultSrc?: DirectiveValues;
scriptSrc?: DirectiveValues;
scriptSrcElem?: DirectiveValues;
styleSrc?: DirectiveValues;
imgSrc?: DirectiveValues;
connectSrc?: DirectiveValues;
fontSrc?: DirectiveValues;
objectSrc?: DirectiveValues;
mediaSrc?: DirectiveValues;
frameSrc?: DirectiveValues;
sandbox?: DirectiveValues;
reportUri?: DirectiveValues;
childSrc?: DirectiveValues;
formAction?: DirectiveValues;
frameAncestors?: DirectiveValues;
pluginTypes?: DirectiveValues;
baseUri?: DirectiveValues;
reportTo?: DirectiveValues;
workerSrc?: DirectiveValues;
manifestSrc?: DirectiveValues;
prefetchSrc?: DirectiveValues;
navigateTo?: DirectiveValues;
upgradeInsecureRequests?: boolean;
blockAllMixedContent?: boolean;
}
DirectiveValues
string[] | string | boolean
ShopProp
- shop
Shop specific configurations
ShopifyDomains
{
/** Shop specific configurations */
shop?: ShopifyDomains;
}
ShopifyDomains
- checkoutDomain
The production shop checkout domain url.
string
- storeDomain
The production shop domain url.
string
{
/** The production shop checkout domain url. */
checkoutDomain?: string;
/** The production shop domain url. */
storeDomain?: string;
}
ContentSecurityPolicy
- header
The content security policy header
string
- nonce
A randomly generated nonce string that should be passed to any custom `script` element
string
- NonceProvider
ComponentType<{children: ReactNode}>
{
/** A randomly generated nonce string that should be passed to any custom `script` element */
nonce: string;
/** The content security policy header */
header: string;
NonceProvider: ComponentType<{children: ReactNode}>;
}
Was this section helpful?
Example code
import {ServerRouter} from 'react-router';
import {isbot} from 'isbot';
import {renderToReadableStream} from 'react-dom/server';
import {createContentSecurityPolicy} from '@shopify/hydrogen';
export default async function handleRequest(
request,
responseStatusCode,
responseHeaders,
remixContext,
) {
const {nonce, header, NonceProvider} = createContentSecurityPolicy({
// pass a custom directive to load content from a third party domain
styleSrc: [
"'self'",
'https://cdn.shopify.com',
'https://some-custom-css.cdn',
],
});
const body = await renderToReadableStream(
<NonceProvider>
<ServerRouter context={remixContext} url={request.url} nonce={nonce} />
</NonceProvider>,
{
nonce,
signal: request.signal,
onError(error) {
// eslint-disable-next-line no-console
console.error(error);
responseStatusCode = 500;
},
},
);
if (isbot(request.headers.get('user-agent'))) {
await body.allReady;
}
responseHeaders.set('Content-Type', 'text/html');
responseHeaders.set('Content-Security-Policy', header);
return new Response(body, {
headers: responseHeaders,
status: responseStatusCode,
});
}
examples
Example code
description
I am the default example
JavaScript
import {ServerRouter} from 'react-router'; import {isbot} from 'isbot'; import {renderToReadableStream} from 'react-dom/server'; import {createContentSecurityPolicy} from '@shopify/hydrogen'; export default async function handleRequest( request, responseStatusCode, responseHeaders, remixContext, ) { const {nonce, header, NonceProvider} = createContentSecurityPolicy({ // pass a custom directive to load content from a third party domain styleSrc: [ "'self'", 'https://cdn.shopify.com', 'https://some-custom-css.cdn', ], }); const body = await renderToReadableStream( <NonceProvider> <ServerRouter context={remixContext} url={request.url} nonce={nonce} /> </NonceProvider>, { nonce, signal: request.signal, onError(error) { // eslint-disable-next-line no-console console.error(error); responseStatusCode = 500; }, }, ); if (isbot(request.headers.get('user-agent'))) { await body.allReady; } responseHeaders.set('Content-Type', 'text/html'); responseHeaders.set('Content-Security-Policy', header); return new Response(body, { headers: responseHeaders, status: responseStatusCode, }); }
TypeScript
import type {EntryContext} from '@shopify/remix-oxygen'; import {ServerRouter} from 'react-router'; import {isbot} from 'isbot'; import {renderToReadableStream} from 'react-dom/server'; import {createContentSecurityPolicy} from '@shopify/hydrogen'; export default async function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, ) { const {nonce, header, NonceProvider} = createContentSecurityPolicy({ // pass a custom directive to load content from a third party domain styleSrc: [ "'self'", 'https://cdn.shopify.com', 'https://some-custom-css.cdn', ], }); const body = await renderToReadableStream( <NonceProvider> <ServerRouter context={remixContext} url={request.url} nonce={nonce} /> </NonceProvider>, { nonce, signal: request.signal, onError(error) { // eslint-disable-next-line no-console console.error(error); responseStatusCode = 500; }, }, ); if (isbot(request.headers.get('user-agent'))) { await body.allReady; } responseHeaders.set('Content-Type', 'text/html'); responseHeaders.set('Content-Security-Policy', header); return new Response(body, { headers: responseHeaders, status: responseStatusCode, }); }