Skip to content

fix(server): harden RTE demo path resolution and prevent path traversal#3090

Open
JuliaMV wants to merge 1 commit intodevelopfrom
EPMSPRT-2552
Open

fix(server): harden RTE demo path resolution and prevent path traversal#3090
JuliaMV wants to merge 1 commit intodevelopfrom
EPMSPRT-2552

Conversation

@JuliaMV
Copy link
Copy Markdown
Collaborator

@JuliaMV JuliaMV commented Apr 10, 2026

Problem

Snyk SAST (rule Javascript/Pt, CWE-23): unsanitized input from the HTTP request body was used when resolving the path for fs.readFileSync in server/api/RTEDemoApi.ts (POST /get-demo-doc-content). The handler attempted a path check but did not return after rejecting unsafe paths, so execution could still reach readFileSync outside the intended rte_contents directory.

Root cause

  1. After a failed containment check, the handler called res.send(null) but did not exit, so the code could continue to existsSync / readFileSync for the same resolved path.
  2. startsWith(contentDir) is a weaker pattern than resolving the base directory and using path.relative for containment.
  3. The base path for rte_contents was inconsistent with the compiled server layout (server/build/api → repo public/), compared to get-contents-list.

Fix

  • Resolve contentDir with path.resolve(__dirname, '../../../public/rte_contents') and require path.relative(contentDir, docContentPath) to stay inside the directory (no .. prefix, not absolute).
  • Return immediately after res.send(null) when the path is invalid or the file is missing.
  • Align get-contents-list with the same public/rte_contents base path.

Files: server/api/RTEDemoApi.ts

How to verify

  • cd server && yarn build
  • Run the docs server as usual; call POST /api/get-demo-doc-content with a safe name (existing JSON under public/rte_contents) and confirm a 200 and JSON body.
  • Retry with a traversal-style name (e.g. containing .. segments); expect null response and no read outside public/rte_contents.

Affected areas for QA

  • Affected: Node documentation server only (server/), RTE demo API: POST .../get-demo-doc-content and GET .../get-contents-list if your tests hit those routes.
  • Not affected: Published @epam/uui npm packages, app UI bundles, or component library behavior.
  • Smoke-test: Docs site flows that load RTE demo content from public/rte_contents (if used in your environment).

Jira

@JuliaMV JuliaMV requested a review from MSt1ch April 10, 2026 14:26
@github-actions
Copy link
Copy Markdown

Generated by: track-bundle-size
Generated at: Fri, 10 Apr 2026 14:35:59 GMT
Bundle size diff (in kBytes). Not gzipped. Both CSS & JS included.
Baseline: v6.3.1 (2025-12-03)
CI Status: ok

Module Baseline Size
(v6.3.1)
Size Diff Within
Threshold
Threshold
(min - max)
templateApp 693.09 684.56 -8.52
js:-6.19
css:-2.33
🆗 623.78 - 762.39
@epam/app 5586.96 5524.51 -62.45
js:-62.82
css:+0.37
🆗 5028.26 - 6145.65
@epam/electric 5.04 5.04 0
js:0
css:0
🆗 4.53 - 5.54
@epam/promo 55.61 55.57 -0.05
js:0
css:-0.05
🆗 50.05 - 61.17
@epam/uui-extra 0.21 0.21 0
js:0
css:0
🆗 0.19 - 0.23
@epam/loveship 92.81 96.24 +3.44
js:+3.49
css:-0.05
🆗 83.53 - 102.09
@epam/uui-components 257.49 260.7 +3.2
js:+1.68
css:+1.52
🆗 231.75 - 283.25
@epam/uui-core 324.75 329.08 +4.33
js:+4.33
css:0
🆗 292.27 - 357.23
@epam/uui-db 41.63 41.72 +0.08
js:+0.08
css:0
🆗 37.47 - 45.8
@epam/uui-docs 181.03 194.76 +13.74
js:+13.75
css:0
🆗 162.92 - 199.13
@epam/uui-editor 174.1 172.5 -1.6
js:-1.6
css:+0
🆗 156.69 - 191.51
@epam/uui-timeline 75.5 75.49 -0.01
js:0
css:0
🆗 67.95 - 83.05
@epam/uui 527.51 548.3 +20.79
js:+4.13
css:+16.66
🆗 474.76 - 580.26
new sizes (raw)

To set the sizes as a new baseline, you can copy/paste next content to the uui-build/config/bundleSizeBaseLine.json and commit the file.

{
  "version": "6.4.4",
  "timestamp": "2026-04-10",
  "sizes": {
    "templateApp": {
      "css": 255089,
      "js": 445904
    },
    "@epam/app": {
      "css": 720897,
      "js": 4936201
    },
    "@epam/electric": {
      "css": 2275,
      "js": 2883
    },
    "@epam/promo": {
      "css": 47756,
      "js": 9145
    },
    "@epam/uui-extra": {
      "css": 0,
      "js": 213
    },
    "@epam/loveship": {
      "css": 55330,
      "js": 43227
    },
    "@epam/uui-components": {
      "css": 25157,
      "js": 241794
    },
    "@epam/uui-core": {
      "css": 0,
      "js": 336983
    },
    "@epam/uui-db": {
      "css": 0,
      "js": 42718
    },
    "@epam/uui-docs": {
      "css": 2152,
      "js": 197287
    },
    "@epam/uui-editor": {
      "css": 12954,
      "js": 163688
    },
    "@epam/uui-timeline": {
      "css": 2199,
      "js": 75104
    },
    "@epam/uui": {
      "css": 215800,
      "js": 345661
    }
  }
}

Generated by: generate-components-api
CI Status: ok

Total amount of exported types/props without JSDoc comments

Amount
Types 338 (+0) 🆗
Props 220 (+0) 🆗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants