[ 
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)

Reply via email to