Spaces:
Sleeping
Sleeping
nyk commited on
fix: remove CSP nonce from style-src to unblock reagraph canvas (#425)
Browse filesReplace style-src nonce directive with unsafe-inline to support
reagraph's runtime <style> injection. Add style-src-elem and
style-src-attr directives for CSP Level 3 compliance. Extend
fitNodesInView retries from 2 to 4 for more reliable canvas sizing.
Closes #414
Supersedes #415
src/components/panels/memory-graph.tsx
CHANGED
|
@@ -267,9 +267,11 @@ export function MemoryGraph() {
|
|
| 267 |
useEffect(() => {
|
| 268 |
if (!graphNodes.length) return
|
| 269 |
// reagraph force layout needs time to settle before fitNodesInView works
|
| 270 |
-
const t1 = setTimeout(() => graphRef.current?.fitNodesInView(), 800)
|
| 271 |
-
const t2 = setTimeout(() => graphRef.current?.fitNodesInView(),
|
| 272 |
-
|
|
|
|
|
|
|
| 273 |
}, [graphNodes.length, selectedAgent])
|
| 274 |
|
| 275 |
// Navigation helpers
|
|
|
|
| 267 |
useEffect(() => {
|
| 268 |
if (!graphNodes.length) return
|
| 269 |
// reagraph force layout needs time to settle before fitNodesInView works
|
| 270 |
+
const t1 = setTimeout(() => graphRef.current?.fitNodesInView(undefined, { animated: false }), 800)
|
| 271 |
+
const t2 = setTimeout(() => graphRef.current?.fitNodesInView(undefined, { animated: false }), 2500)
|
| 272 |
+
const t3 = setTimeout(() => graphRef.current?.fitNodesInView(undefined, { animated: false }), 5000)
|
| 273 |
+
const t4 = setTimeout(() => graphRef.current?.fitNodesInView(undefined, { animated: false }), 8000)
|
| 274 |
+
return () => { clearTimeout(t1); clearTimeout(t2); clearTimeout(t3); clearTimeout(t4) }
|
| 275 |
}, [graphNodes.length, selectedAgent])
|
| 276 |
|
| 277 |
// Navigation helpers
|
src/lib/__tests__/csp.test.ts
CHANGED
|
@@ -6,7 +6,9 @@ describe('buildMissionControlCsp', () => {
|
|
| 6 |
const csp = buildMissionControlCsp({ nonce: 'nonce-123', googleEnabled: false })
|
| 7 |
|
| 8 |
expect(csp).toContain(`script-src 'self' 'nonce-nonce-123' 'strict-dynamic'`)
|
| 9 |
-
expect(csp).toContain(
|
|
|
|
|
|
|
| 10 |
})
|
| 11 |
})
|
| 12 |
|
|
@@ -19,6 +21,6 @@ describe('buildNonceRequestHeaders', () => {
|
|
| 19 |
})
|
| 20 |
|
| 21 |
expect(headers.get('x-nonce')).toBe('nonce-123')
|
| 22 |
-
expect(headers.get('Content-Security-Policy')).toContain(
|
| 23 |
})
|
| 24 |
})
|
|
|
|
| 6 |
const csp = buildMissionControlCsp({ nonce: 'nonce-123', googleEnabled: false })
|
| 7 |
|
| 8 |
expect(csp).toContain(`script-src 'self' 'nonce-nonce-123' 'strict-dynamic'`)
|
| 9 |
+
expect(csp).toContain("style-src 'self' 'unsafe-inline'")
|
| 10 |
+
expect(csp).toContain("style-src-elem 'self' 'unsafe-inline'")
|
| 11 |
+
expect(csp).toContain("style-src-attr 'unsafe-inline'")
|
| 12 |
})
|
| 13 |
})
|
| 14 |
|
|
|
|
| 21 |
})
|
| 22 |
|
| 23 |
expect(headers.get('x-nonce')).toBe('nonce-123')
|
| 24 |
+
expect(headers.get('Content-Security-Policy')).toContain("style-src 'self' 'unsafe-inline'")
|
| 25 |
})
|
| 26 |
})
|
src/lib/csp.ts
CHANGED
|
@@ -7,7 +7,9 @@ export function buildMissionControlCsp(input: { nonce: string; googleEnabled: bo
|
|
| 7 |
`object-src 'none'`,
|
| 8 |
`frame-ancestors 'none'`,
|
| 9 |
`script-src 'self' 'nonce-${nonce}' 'strict-dynamic' blob:${googleEnabled ? ' https://accounts.google.com' : ''}`,
|
| 10 |
-
`style-src 'self' '
|
|
|
|
|
|
|
| 11 |
`connect-src 'self' ws: wss: http://127.0.0.1:* http://localhost:* https://cdn.jsdelivr.net`,
|
| 12 |
`img-src 'self' data: blob:${googleEnabled ? ' https://*.googleusercontent.com https://lh3.googleusercontent.com' : ''}`,
|
| 13 |
`font-src 'self' data:`,
|
|
|
|
| 7 |
`object-src 'none'`,
|
| 8 |
`frame-ancestors 'none'`,
|
| 9 |
`script-src 'self' 'nonce-${nonce}' 'strict-dynamic' blob:${googleEnabled ? ' https://accounts.google.com' : ''}`,
|
| 10 |
+
`style-src 'self' 'unsafe-inline'`,
|
| 11 |
+
`style-src-elem 'self' 'unsafe-inline'`,
|
| 12 |
+
`style-src-attr 'unsafe-inline'`,
|
| 13 |
`connect-src 'self' ws: wss: http://127.0.0.1:* http://localhost:* https://cdn.jsdelivr.net`,
|
| 14 |
`img-src 'self' data: blob:${googleEnabled ? ' https://*.googleusercontent.com https://lh3.googleusercontent.com' : ''}`,
|
| 15 |
`font-src 'self' data:`,
|