Skip to content

Commit 49012db

Browse files
842uTkDodoautofix-ci[bot]
authored
fix(query-devtools): set window.__nonce__ in setupStyleSheet (#10736)
* fix(query-devtools): set window.__nonce__ in setupStyleSheet * test(query-devtools): add tests for window.__nonce__ in setupStyleSheet * chore: add changeset * fix: merge conflicts * formatting * ci: apply automated fixes --------- Co-authored-by: Dominik Dorfmeister 🔮 <office@dorfmeister.cc> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent a4587b6 commit 49012db

3 files changed

Lines changed: 26 additions & 1 deletion

File tree

.changeset/mighty-banks-mate.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@tanstack/query-devtools': patch
3+
---
4+
5+
`setupStyleSheet` now sets `window.__nonce__` when a `styleNonce` is provided.
6+
7+
The devtools use [goober](https://goober.js.org/) for CSS-in-JS, which reads `window.__nonce__` every time it creates or accesses its style element. Without this, goober overwrote the nonce with `undefined`, causing CSP violations even when `styleNonce` was correctly passed to `<ReactQueryDevtools>`.

packages/query-devtools/src/__tests__/utils.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,7 @@ describe('Utils tests', () => {
982982
describe('setupStyleSheet', () => {
983983
afterEach(() => {
984984
document.head.querySelector('#_goober')?.remove()
985+
delete (window as any).__nonce__
985986
})
986987

987988
it('should not insert any style tag when "nonce" is missing', () => {
@@ -1055,6 +1056,18 @@ describe('Utils tests', () => {
10551056
'shadow-nonce',
10561057
)
10571058
})
1059+
1060+
it('should set window.__nonce__ so goober preserves the nonce on its style element', () => {
1061+
setupStyleSheet('test-nonce')
1062+
1063+
expect((window as any).__nonce__).toBe('test-nonce')
1064+
})
1065+
1066+
it('should not set window.__nonce__ when nonce is missing', () => {
1067+
setupStyleSheet()
1068+
1069+
expect((window as any).__nonce__).toBeUndefined()
1070+
})
10581071
})
10591072

10601073
describe('sortFns', () => {

packages/query-devtools/src/utils.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,12 @@ export const deleteNestedDataByPath = (
307307
// Sets up the goober stylesheet
308308
// Adds a nonce to the style tag if needed
309309
export const setupStyleSheet = (nonce?: string, target?: ShadowRoot) => {
310-
if (!nonce) return
310+
if (!nonce)
311+
return // Goober reads window.__nonce__ every time it creates or accesses its style
312+
// element (el.nonce = window.__nonce__). Without this, goober overwrites the
313+
// nonce we set on the pre-created element with undefined, clearing it.
314+
;(window as any).__nonce__ = nonce
315+
311316
const root = target ?? document.head
312317
if (root.querySelector('#_goober')) return
313318
const styleTag = document.createElement('style')

0 commit comments

Comments
 (0)