[ 
https://issues.apache.org/jira/browse/ATLAS-5417?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18119075#comment-18119075
 ] 

ASF subversion and git services commented on ATLAS-5417:
--------------------------------------------------------

Commit d266321e9d8a584de446a1d8e673654e304587fd in atlas's branch 
refs/heads/ATLAS-5417_UI_unescapeString from Prasad Pawar
[ https://gitbox.apache.org/repos/asf?p=atlas.git;h=d266321e9 ]

ATLAS-5417: Atlas UI: Fix unescaped business metadata string rendering in 
Classic UI basic search results table.


> Atlas UI: Fix unescaped business metadata string rendering in Classic UI 
> basic search results table.
> ----------------------------------------------------------------------------------------------------
>
>                 Key: ATLAS-5417
>                 URL: https://issues.apache.org/jira/browse/ATLAS-5417
>             Project: Atlas
>          Issue Type: Bug
>          Components: atlas-webui
>    Affects Versions: 3.0.0
>            Reporter: Prasad P. Pawar
>            Assignee: Prasad P. Pawar
>            Priority: Major
>
> h3. Summary
> Business metadata string attribute values could be stored via the REST API 
> with HTML markup and were shown in the Classic UI ({{{}dashboardv2{}}}) basic 
> search results without proper content filtering. When a user with appropriate 
> access opened search results containing those values, the browser could 
> interpret the markup as active content instead of plain or safely formatted 
> text.
> This ticket addresses incorrect rendering behavior in the search results 
> table for business metadata string columns.
> h3. Problem / Root Cause
> Metadata text is stored and returned as provided on the write path. In 
> Classic UI basic search:
>  # Business metadata string columns were flagged as {{isEditorValue}} 
> (rich-text/editor fields).
>  # The search table renderer skipped HTML entity escaping for those values.
>  # Raw values were inserted into the DOM via Backgrid {{{}HtmlCell{}}}.
>  # Values written through the REST API bypassed the UI-only sanitizer used on 
> the entity edit path.
> Affected area: Classic UI ({{{}dashboardv2{}}}) — basic search results table, 
> business metadata string attribute columns only.
> Not affected: React UI ({{{}dashboard/{}}}) — search and detail views already 
> use React text escaping or HTML allowlist sanitization.
> h3. Solution Implemented
> ||File||Change||
> |{{dashboardv2/public/js/utils/CommonViewFunction.js}}|When {{isEditorValue}} 
> is set, route values through {{Utils.sanitizeHtmlContent()}} (DOMPurify 
> allowlist) instead of inserting raw HTML|
> |{{dashboardv2/public/js/views/search/SearchResultLayoutView.js}}|Document 
> why {{checkIsEditorValue}} marks business metadata string columns for 
> sanitized rich-text display|
>  
> Allowed markup after fix: {{{}b{}}}, {{{}em{}}}, {{{}strong{}}}, {{{}u{}}}, 
> {{{}a[href]{}}}, lists, {{{}p{}}}, headings, {{strike}}
> Removed/blocked: {{{}script{}}}, {{{}img{}}}, {{{}iframe{}}}, event handlers, 
> {{javascript:}} URLs
> h4. Overall code coverage (after changes)
> {code:java}
> Project overall: 88.82% statements | 82.15% branches | 80.19% functions 
> Tests: 4947 passed / 197 suites Changed-area subset: Utils.ts 92.79% 
> statements HtmlRenderer.tsx 100.00% statements ShowMoreText.tsx 100.00% 
> statements commonComponents.tsx 100.00% statements{code}
> Classic UI ({{{}dashboardv2{}}}) has no Jest suite — regression covered by 
> manual QA below.
> h3. Manual test steps (Classic UI)
> Preconditions: Business metadata with a string attribute (e.g. 
> {{{}bm1.notes{}}}); entity with that attribute set via REST API.
> ||Step||Action||Expected result||
> |1|Set attribute via REST API to {{<img src=x onerror="alert(1)">}}|Value 
> stored in metadata|
> |2|Log in to Classic UI, run basic search, enable BM column|No alert/dialog; 
> cell empty or shows safe text only|
> |3|Set value to {{<p>Hello <strong>world</strong></p>}}|Cell shows formatted 
> text: Hello world|
> |4|Set value to {{Plain text notes}}|Cell shows: {{Plain text notes}}|
> ----
> h3. Example: test input vs UI output
> h4. Example 1 — Active markup in metadata (Classic UI search)
> Input (REST API):
> <img src=x onerror="alert('test')">
> || ||Before fix||After fix||
> |UI behavior|Browser dialog / script runs|Nothing runs|
> |Cell display|Image tag processed|Empty or safe text only|
> |DOM|{{<img>}} element present|No {{<img>}} element|
> ----
> h4. Example 2 — Script tag in metadata (Classic UI search)
> Input (REST API):
> <script>alert('test')</script><p>Safe notes</p>
> || ||Before fix||After fix||
> |UI behavior|Script may run|Script does not run|
> |Cell display|Mixed|Safe notes (with optional {{<p>}} formatting)|
> |DOM|{{<script>}} may be present|No {{<script>}} tag|
> ----
> h4. Example 3 — Safe rich text (Classic UI search)
> Input (REST API):
> <p>Review <strong>approved</strong> by team</p>
> || ||After fix||
> |Cell display|Review approved by team|
> |Behavior|Formatting preserved; no active markup|
> ----
> h4. Example 4 — Same payload in React UI search (reference)
> Input: {{<img src=x onerror="alert(1)">}}
> || ||React UI output||
> |Cell display|Literal text: {{<img src=x onerror="alert(1)">}}|
> |DOM|No {{<img>}} element (React auto-escapes JSX text)|
> ----
> h3. Build & quality gates
> ||Check||Result||
> |ESLint|0 errors|
> |TypeScript|Pass|
> |Vite build|Pass (~6.85s)|
> |Jest (serial)|4947/4947 pass|
> h3. Acceptance criteria
>  * Business metadata string values in Classic UI basic search render through 
> DOMPurify allowlist
>  * Active markup in metadata does not run in the browser when viewing search 
> results
>  * Safe rich text (bold, paragraphs, links) still displays correctly
>  * All 4947 automated tests pass
>  * Manual Classic UI QA completed per steps above



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to