Skip to content

research: CSP unsafe-inline removal blocked by Radix UI #925

@Aureliolo

Description

@Aureliolo

Context

Our CSP (web/security-headers.conf) requires style-src 'unsafe-inline' because Radix UI primitives inject dynamic inline styles at runtime. This issue tracks the upstream blocker and potential migration paths.

Extracted from #820. Framer Motion's portion is already fixable (tracked in #924).

The problem

Radix UI violates CSP in two ways that cannot be fixed with nonces:

1. Inline style attributes on DOM elements

Popper (used by Popover, Tooltip, Select, DropdownMenu, HoverCard), DismissableLayer, VisuallyHidden, and others set CSS custom properties via style="--radix-*: ...". Nonces cannot fix this -- nonces only work on <style> elements, not style attributes.

Affected components we use: Dialog, AlertDialog (ConfirmDialog), Popover (ThemeToggle), FocusScope.

2. <style> tag injection via transitive dependencies

react-remove-scroll / react-style-singleton (used by Dialog, AlertDialog, Popover, Select, Menu) inject <style> tags at runtime. The upstream issue has been open since February 2020.

Upstream status (stagnant)

Date Event
2024-02 Nonce prop merged for ScrollArea/Select only (PR #2728)
2024-09 CSS export approach PR rejected by maintainer (PR #3131)
2024-10 Maintainer said "near the top of my todo list"
2025-04 Community asked for update -- no response
2025-07 Community asked again -- no response
2026-01 Community asked again -- no response
2026-02 Discussion #3130 closed with no resolution

Open issues: #3063, #3117. No maintainer engagement.

Options to evaluate

A. Wait for upstream fix

  • Pros: Zero effort
  • Cons: 18+ months of silence, no committed timeline, architectural issue (inline style attrs) may never be fixed

B. Migrate to Base UI

  • Base UI's CSPProvider has first-class CSP support with context-based nonce propagation and disableStyleElements option
  • Cons: Major migration away from shadcn/ui + Radix. Would affect every component.

C. Patch Radix packages

  • Maintainer has suggested patching as a short-term option
  • Cons: Maintenance burden on every Radix update, may not cover all cases (especially inline style attrs)

D. Accept unsafe-inline for style-src

  • Current approach. unsafe-inline for styles is significantly less dangerous than for scripts (no code execution). The real XSS vector is script-src, which is already locked down to 'self'.
  • Cons: Does not meet strictest CSP policies, CSS injection could theoretically exfiltrate DOM content

Action items

  • Periodically check upstream Radix issues for movement
  • If option B is considered, evaluate Base UI migration scope and breaking changes
  • Document the accepted risk of style-src 'unsafe-inline' in docs/security.md

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    prio:lowNice to have, can deferscope:webVue 3 dashboardtype:researchEvaluate options, make tech decisionsv0.6Minor version v0.6v0.6.0Patch release v0.6.0

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions