[
https://issues.apache.org/jira/browse/ATLAS-5389?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18108291#comment-18108291
]
ASF subversion and git services commented on ATLAS-5389:
--------------------------------------------------------
Commit 8706ccc7f704e8232c3c0f90dbe131b4959bc2a6 in atlas's branch
refs/heads/ATLAS-5389_broswerResourcePolicy from Prasad Pawar
[ https://gitbox.apache.org/repos/asf?p=atlas.git;h=8706ccc7f7 ]
ATLAS-5389: Atlas React Dashboard — Align UI with strict browser resource
policy (nonce-based script/style handling)
> Atlas React Dashboard — Align UI with strict browser resource policy
> (nonce-based script/style handling)
> --------------------------------------------------------------------------------------------------------
>
> Key: ATLAS-5389
> URL: https://issues.apache.org/jira/browse/ATLAS-5389
> Project: Atlas
> Issue Type: Bug
> Components: atlas-webui
> Reporter: Prasad P. Pawar
> Assignee: Prasad P. Pawar
> Priority: Major
>
> DAST scan findings on Atlas UI endpoints show that current browser resource
> policy headers allow inline scripts, dynamic JavaScript evaluation, and
> inline styles. Server-side work will introduce per-request nonce support;
> this ticket covers React Dashboard UI only ({{{}/n3/{}}}).
> h3. Scope
> In scope
> * React Dashboard ({{{}dashboard/{}}} module, served at
> {{{}/n3/index.html{}}})
> * Client-side changes to work with nonce-based script/style policy
> * Unit tests for new/changed React code
> * Smoke validation of main dashboard flows under the updated policy
> Out of scope
> * Classic Dashboardv2 (Backbone UI at {{{}/index.html{}}})
> * Server-side filter/header implementation (tracked separately)
> * Login/error page templates in {{webapp/}}
> h3. Problem (UI perspective)
> Under the planned strict policy:
> # Inline scripts in HTML shell — must receive a server-injected nonce or be
> externalized.
> # MUI/Emotion runtime {{<style>}} tags — must use the same nonce as the CSP
> header, or styles will be blocked.
> # Lineage tooltip HTML — uses inline {{style=}} attributes in dynamically
> built strings; may need CSS class migration.
>
> React {{{}style={{}}}} props and MUI {{sx=}} are handled differently: {{sx}}
> goes through Emotion (needs nonce); {{{}style={{}}}} is governed by
> {{style-src-attr}} (server policy decision, no React code change if
> transitional allowance is kept).
> h3. Planned Fix
> Phase 1 — Client nonce wiring (P0)
> * Add {{dashboard/src/utils/cspNonce.ts}} to read nonce from {{<meta
> name="csp-nonce">}} or the first {{<script nonce="...">}} tag.
> * Update {{{}dashboard/src/Main.tsx{}}}:
> ** Create Emotion cache with {{createCache(\{ key: 'css', nonce:
> getCspNonce() })}}
> ** Wrap app in {{CacheProvider}} + {{StyledEngineProvider}}
> * Add unit tests: {{{}cspNonce.test.ts{}}}, update {{Main.test.tsx}}
> Phase 2 — Inline content cleanup (P1)
> * Refactor lineage tooltip inline styles in
> {{dashboard/src/views/Lineage/atlas-lineage/src/index.js}} to CSS classes.
> * Review {{dangerouslySetInnerHTML}} usage in {{commonComponents.tsx}} and
> related components (content handling, not policy headers).
> Phase 3 — Validation (P0)
> * Smoke test: login → search → entity detail → lineage → admin → statistics.
> * Confirm no browser console policy violations on {{/n3/}} routes.
> * Update test documentation.
> h3. Files to change (approx.)
> ||File||Change||
> |{{dashboard/src/utils/cspNonce.ts}}|New — nonce reader utility|
> |{{dashboard/src/utils/_{_}tests{_}_/cspNonce.test.ts}}|New — unit tests|
> |{{dashboard/src/Main.tsx}}|Wire Emotion cache with nonce|
> |{{dashboard/src/_{_}tests{_}_/Main.test.tsx}}|Assert nonce wiring|
> |{{dashboard/src/views/Lineage/atlas-lineage/src/index.js}}|Replace inline
> tooltip styles with CSS classes|
> |{{dashboard/index.html}}|Optional {{<meta name="csp-nonce">}} placeholder
> for server injection|
> Estimated total: ~6–8 files, ~150 lines of change
> h3. Dependencies
> * Server must deploy per-request nonce generation and HTML nonce injection
> before this UI work is validated in an integrated environment.
> * Vite build already externalizes JS bundles; no build pipeline changes
> expected.
> h3. Acceptance Criteria
> * React Dashboard loads and renders correctly at {{/n3/index.html}} under
> nonce-based policy
> * MUI/Emotion components render without blocked styles
> * No browser console policy violations on primary user flows
> * Unit tests added/updated for {{cspNonce.ts}} and {{Main.tsx}}
> * Lineage tooltips display correctly after CSS class
> h2. Manual Testing Guide
> h3. Prerequisites
> ** Atlas server running (local or dev environment)
> ** Backend CSP changes deployed (PR #742 or equivalent with HTML nonce
> injection)
> ** Browser DevTools (Chrome/Firefox)
> ** Valid Atlas login credentials
> ----
> h3. Part 1: Server-Side Verification
> h4. Step 1 — Check CSP response header
> curl -I -k -u admin:admin \
> https://localhost:21000/n3/index.html
> Expected response header:
> Content-Security-Policy: default-src 'self'; script-src 'self'
> 'nonce-AbCdEf123456' blob:; style-src 'self' 'nonce-AbCdEf123456'; ...
>
> Verify:
> ** No {{'unsafe-inline'}} in {{script-src}}
> ** No {{'unsafe-eval'}} in {{script-src}}
> ** {{'nonce-...'}} present in both {{script-src}} and {{style-src}}
> Example (good):
> Content-Security-Policy: default-src 'self'; script-src 'self'
> 'nonce-Xk9mP2qR7sT4' blob:; connect-src 'self'; img-src 'self' blob: data:;
> style-src 'self' 'nonce-Xk9mP2qR7sT4'; font-src 'self' data:; object-src
> 'none'; base-uri 'self'; frame-ancestors 'none';
>
> Example (bad — would fail DAST):
> Content-Security-Policy: ... script-src 'self' 'unsafe-inline' 'unsafe-eval'
> ...
>
> ----
> h4. Step 2 — Check HTML nonce injection
> curl -k -u admin:admin \
> https://localhost:21000/n3/index.html|grep-E'csp-nonce|nonce='
>
> Expected output (once backend HTML injection is in place):
> <meta name="csp-nonce" content="Xk9mP2qR7sT4" />
> <script type="module" nonce="Xk9mP2qR7sT4" crossorigin
> src="./assets/index-xxx.js"></script>
>
> Verify:
> ** Meta {{content}} matches CSP header nonce (without {{nonce-}} prefix)
> ** Script tags have {{nonce="..."}} attribute
> ** Nonce value is the same across meta, script, and header
> ----
> h4. Step 3 — Confirm nonce consistency per request
> Run twice and compare:
> curl -I -k -u admin:admin https://localhost:21000/n3/index.html 2>&1 | grep
> -i content-security-policy
> curl -I -k -u admin:admin https://localhost:21000/n3/index.html 2>&1 | grep
> -i content-security-policy
>
> Expected: Different nonce on each request (per-request generation).
> ----
> h4. Step 4 — Check login page (backend scope)
> curl -k https://localhost:21000/login.jsp 2>&1 | grep -E 'csp-nonce|nonce='
>
> Login page CSP is backend-owned; confirm it is in scope for the backend PR.
> ----
> h3. Part 2: UI-Side Verification (Browser)
> h4. Step 1 — Open React Dashboard
> ## Log in to Atlas
> ## Navigate to React UI: {{https://<host>:<port>/n3/index.html}}
> ## Open DevTools → Console tab
> Expected: No Content Security Policy violation errors.
> Example violation (if broken):
> Refused to apply inline style because it violates the following Content
> Security Policy directive: "style-src 'self' 'nonce-...'".
>
> ----
> h4. Step 2 — Verify nonce is read by the app
> In DevTools Console, run:
> // Check meta tag
> document.querySelector('meta[name="csp-nonce"]')?.getAttribute('content')
>
> // Check script nonce
> document.querySelector('script[nonce]')?.getAttribute('nonce')
>
> // Check Emotion style tags have nonce
> document.querySelectorAll('style[data-emotion]').forEach(s =>
> console.log(s.getAttribute('nonce')))
>
> Expected (with backend deployed):
> "Xk9mP2qR7sT4" // meta content
> "Xk9mP2qR7sT4" // script nonce
> "Xk9mP2qR7sT4" // emotion style nonce (multiple style tags)
> "Xk9mP2qR7sT4"
> ...
>
> Expected (local dev without backend injection):
> "" // empty meta — app still loads, no nonce on styles
> undefined // no script nonce
> null // emotion styles without nonce (OK in dev without strict CSP)
>
> ----
> h4. Step 3 — Visual smoke test
> ||#||Flow||What to check||
> |1|Dashboard home|Cards, charts, sidebar render with correct MUI styling|
> |2|Search|Search bar, filters, results table styled correctly|
> |3|Entity detail|Tabs, properties, labels render properly|
> |4|Lineage tab|Graph renders (note: tooltip inline styles are a follow-up)|
> |5|Admin → Type system|Tree view, MUI components styled|
> |6|Toast notifications|Trigger an action that shows a toast — styled
> correctly|
> Expected: No unstyled/broken UI. No console CSP errors.
> ----
> h4. Step 4 — Network tab verification
> ## DevTools → Network tab
> ## Reload {{/n3/index.html}}
> ## Click the document request → Headers
> Check Response Headers:
> content-security-policy: ... 'nonce-AbCdEf123456' ...
> Check Response body (Preview):
> <meta name="csp-nonce" content="AbCdEf123456" />
> Confirm header nonce ({{{}nonce-AbCdEf123456{}}}) matches meta content
> ({{{}AbCdEf123456{}}}).
> ----
> h4. Step 5 — Simulate strict CSP locally (optional, advanced)
> For local UI testing before backend is ready:
> ## Start dev server:
> cd dashboard && npm run dev
> ## Temporarily edit {{{}dashboard/index.html{}}}:
> <meta name="csp-nonce" content="test-local-nonce" />
> ## Add a strict CSP meta tag for testing:
> <meta http-equiv="Content-Security-Policy"
> content="default-src 'self'; script-src 'self' 'nonce-test-local-nonce';
> style-src 'self' 'nonce-test-local-nonce'; connect-src 'self'
> ws://localhost:* http://localhost:*;"/>
>
> ## Open {{http://localhost:5173/n3/}}
> ## In Console, verify:
> document.querySelector('meta[name="csp-nonce"]').content
> // → "test-local-nonce"
>
> [...document.querySelectorAll('style[data-emotion]')].every(
> s=>s.getAttribute('nonce')==='test-local-nonce'
> )
> // → true (if UI changes are working)
> Expected: Dashboard renders fully styled with zero CSP console errors.
> ----
> h3. Part 3: End-to-End Checklist
> ||#||Test||Server||UI||Pass criteria||
> |1|CSP header has nonce, no unsafe directives|curl -I|—|Header contains
> {{{}'nonce-...'{}}}, no {{'unsafe-inline'}}|
> |2|HTML meta tag populated|curl HTML|DevTools|Meta content matches header
> nonce|
> |3|Script tags have nonce|curl HTML|DevTools|{{nonce="..."}} on module
> scripts|
> |4|Emotion styles have nonce|—|DevTools|All {{style[data-emotion]}} have
> matching nonce|
> |5|Dashboard renders|—|Browser|No broken/unstyled UI|
> |6|No console CSP errors|—|Browser|Console clean on all flows|
> |7|Search works|—|Browser|Functional + styled|
> |8|Entity detail works|—|Browser|Tabs, properties render|
> |9|Login page works|curl|Browser|Backend scope — no blocked scripts|
--
This message was sent by Atlassian Jira
(v8.20.10#820010)