Skip to content

Commit a65c757

Browse files
justin808claude
andcommitted
Nonce app-level inline scripts in Pro dummy demo pages
Codex review flagged that with the strict CSP enforced globally, demo pages emitting their own inline scripts outside the React on Rails helpers would be blocked: the Apollo examples' apolloStateTag and React Router's StaticRouterProvider hydration-data script. Thread railsContext.cspNonce into those script tags (StaticRouterProvider has a first-class nonce prop). Verified on /react_router in a real browser: zero securitypolicyviolation events and the hydration-data script carries the per-request nonce. These edits also document the recommended pattern for app-level inline scripts under the strict policy (see docs/pro/strict-csp.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 26c20d7 commit a65c757

3 files changed

Lines changed: 13 additions & 3 deletions

File tree

react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ApolloGraphQLApp.server.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { getMarkupFromTree } from '@apollo/client/react/ssr';
2222
import fetch from 'cross-fetch';
2323
import ApolloGraphQL from '../components/ApolloGraphQL';
2424

25-
export default async (props, _railsContext) => {
25+
export default async (props, railsContext) => {
2626
const { csrf, sessionCookie } = props.ssrOnlyProps;
2727
const client = new ApolloClient({
2828
ssrMode: true,
@@ -52,6 +52,9 @@ export default async (props, _railsContext) => {
5252
// you need to return additional property `apolloStateTag`, to fulfill the state for hydration
5353
const apolloStateTag = renderToString(
5454
<script
55+
// Carry the per-request CSP nonce so the strict policy
56+
// (config/initializers/content_security_policy.rb) allows this inline script.
57+
nonce={railsContext.cspNonce}
5558
// eslint-disable-next-line react/no-danger
5659
dangerouslySetInnerHTML={{
5760
__html: `window.__APOLLO_STATE__=${JSON.stringify(initialState).replace(/</g, '\\u003c')};`,

react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/LazyApolloGraphQLApp.server.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type Props = {
3232
};
3333
};
3434

35-
export default async (props: Props, _railsContext: RailsContext) => {
35+
export default async (props: Props, railsContext: RailsContext) => {
3636
const { csrf, sessionCookie } = props.ssrOnlyProps;
3737
const client = new ApolloClient({
3838
ssrMode: true,
@@ -60,6 +60,9 @@ export default async (props: Props, _railsContext: RailsContext) => {
6060
// you need to return additional property `apolloStateTag`, to fulfill the state for hydration
6161
const apolloStateTag = renderToString(
6262
<script
63+
// Carry the per-request CSP nonce so the strict policy
64+
// (config/initializers/content_security_policy.rb) allows this inline script.
65+
nonce={railsContext.cspNonce}
6366
// eslint-disable-next-line react/no-danger
6467
dangerouslySetInnerHTML={{
6568
__html: `

react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/RouterApp.server.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ const dataServerRouter = async (_props, railsContext) => {
2828
const routerContext = await handler.query(request);
2929
const router = createStaticRouter(handler.dataRoutes, routerContext);
3030

31-
return renderToString(<StaticRouterProvider router={router} context={routerContext} />);
31+
// nonce: the strict CSP (config/initializers/content_security_policy.rb) would
32+
// otherwise block the inline hydration-data script StaticRouterProvider emits.
33+
return renderToString(
34+
<StaticRouterProvider router={router} context={routerContext} nonce={railsContext.cspNonce} />,
35+
);
3236
};
3337

3438
export default dataServerRouter;

0 commit comments

Comments
 (0)