Skip to content

Add nonce attribute to immediate hydration inline scripts for CSP compatibility #2350

@ihabadham

Description

@ihabadham

Summary

The immediate hydration scripts generated by generate_component_script and generate_store_script in lib/react_on_rails/pro_helper.rb (lines 27-29 and 52-55) create inline <script> tags without nonce attributes. This makes them incompatible with strict Content Security Policy (CSP) configurations.

Context

React on Rails already handles nonces correctly for console replay scripts via wrap_console_script_with_nonce in helper.rb (lines 440-464), which uses Rails' content_security_policy_nonce(:script) helper. The immediate hydration scripts should follow the same pattern.

Affected Code

lib/react_on_rails/pro_helper.rb:

# generate_component_script (line 27-29)
immediate_script = content_tag(:script, %(
  typeof ReactOnRails === 'object' && ReactOnRails.reactOnRailsComponentLoaded('#{escaped_dom_id}');
).html_safe)

# generate_store_script (line 52-55)
immediate_script = content_tag(:script, <<~JS.strip_heredoc.html_safe
  typeof ReactOnRails === 'object' && ReactOnRails.reactOnRailsStoreLoaded('#{escaped_store_name}');
JS
)

Expected Behavior

When CSP is enabled with nonce-based script-src, these inline scripts should include the request nonce:

<script nonce="abc123...">
  typeof ReactOnRails === 'object' && ReactOnRails.reactOnRailsComponentLoaded('...');
</script>

Suggested Fix

Follow the same pattern as wrap_console_script_with_nonce — call content_security_policy_nonce(:script) and pass it as the nonce: option to content_tag(:script, ...).

Impact

Without this fix, apps that enable strict CSP (without 'unsafe-inline' in script-src) cannot use immediate hydration. The browser blocks the inline scripts, and components fail to hydrate immediately.

Apps with SSR disabled or immediate hydration disabled are not affected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Target this sprint

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions