[security][backport 24.05] Fortify-flagged path traversal, XSS, and info-leak fixes#7555
Merged
Merged
Conversation
…k fixes from PR #7547 Backport of #7547 to release.24.05. - frontend/express/app.js: theme image handler built sendFile path from cookie + URL with only a prefix check, allowing `..` traversal outside /public/themes. Now uses res.sendFile with `root` option so express normalizes the path and rejects traversal natively. - plugins/two-factor-auth setup2fa.html / enter2fa_login.html: hidden username/password inputs used unescaped EJS (`<%-`), enabling reflected XSS via crafted credentials. Switched to escaped `<%=`. - api/utils/common.js: returnRaw / returnMessage / returnOutput logged the entire params object on the "output already closed" branch, which can include req.body/req.headers (passwords, session cookies). Replaced with a small non-sensitive summary (pathname only, no query string). Note: 24.05 has three sites vs two on master (returnRaw exists here). - plugins/sdk/api/api.js: SDK config endpoints echoed raw `'Error: ' + err` to clients, leaking internal details. Now log details server-side and return a generic message. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Backport of security hardening fixes to release.24.05, addressing Fortify-flagged findings around path traversal, reflected XSS, sensitive-log leakage, and internal error leakage to clients.
Changes:
- Escape EJS output for hidden
username/passwordfields in 2FA templates to prevent reflected XSS. - Reduce sensitive logging in
api/utils/common.jswhen responses are already closed. - Stop returning raw internal errors from SDK config endpoints; log server-side and return a generic message.
- Rework theme static file serving to use
res.sendFile(..., { root })andreq.path(but see security comment re: absolute-path bypass).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/two-factor-auth/frontend/public/templates/setup2fa.html | Switch unescaped EJS output to escaped for hidden credential fields. |
| plugins/two-factor-auth/frontend/public/templates/enter2fa_login.html | Switch unescaped EJS output to escaped for hidden credential fields. |
| plugins/sdk/api/api.js | Replace client-facing 'Error: ' + err with server-side logging and generic error response. |
| frontend/express/app.js | Update theme image handler to use req.path and res.sendFile with root to mitigate traversal. |
| api/utils/common.js | Replace full params logging with a non-sensitive summary when output is already closed. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Cookiezaurs
approved these changes
May 11, 2026
- Reject `theme` cookie values that contain path separators, leading dots, or control chars via common.sanitizeFilename. Defense-in-depth on top of res.sendFile's `root` normalization (which already converts absolute paths to relative and blocks `..` traversal via send's `'.' + sep + path` prefix). - Log non-ENOENT / non-403 / non-404 errors from sendFile server-side instead of swallowing them silently; still fall through to next() so a theme misconfiguration doesn't 500 unrelated routes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ar2rsawseen
added a commit
that referenced
this pull request
May 11, 2026
Addresses two Copilot review comments on this PR's theme handler. - Reject `theme` cookie values that contain path separators, leading dots, or control chars via common.sanitizeFilename. Defense-in-depth on top of res.sendFile's `root` normalization (which already converts absolute paths to relative and blocks `..` traversal via send's `'.' + sep + path` prefix). - Log non-ENOENT / non-403 / non-404 errors from sendFile server-side instead of swallowing them silently; still fall through to next() so a theme misconfiguration doesn't 500 unrelated routes. Mirrors the same hardening applied on the 24.05 backport (#7555). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Backport of #7547 to
release.24.05.Addresses real findings from a customer Fortify scan against this branch. False positives and out-of-repo (enterprise plugin / Web SDK) findings will be answered separately to the customer with technical justifications.
Fixes
Path traversal —
frontend/express/app.jsTheme image handler built
sendFilepath fromreq.cookies.theme + req.urlwith only a prefix check on/images/or/geodata/. A URL like/images/../../../etc/passwd(or a maliciousthemecookie) escaped the themes directory. Now usesres.sendFilewith therootoption — express normalizes the path and rejects..traversal natively (recognized by CodeQL as a sanitizer). Also switchedreq.url→req.pathso query strings don't bleed into the filesystem lookup.Reflected XSS —
plugins/two-factor-auth setup2fa.html / enter2fa_login.htmlHidden
username/passwordinputs used unescaped EJS (<%-). A username containing\"><script>broke out of the attribute and executed in the login origin. Switched to escaped<%=. (secret_tokenalready used<%=.)Sensitive data in logs —
api/utils/common.jsreturnRaw/returnMessage/returnOutputdumped the entireparamsobject (incl.req.body,req.headers— passwords, session cookies) on the "output already closed" branch. Replaced with a non-sensitive summary (pathname,apiPath,qstringKeys). Note: 24.05 has three sites here versus two on master —returnRawexists in this branch and was fixed for consistency.Internal error leak to client —
plugins/sdk/api/api.jsSDK config endpoints echoed
'Error: ' + errto clients. Now log details server-side viaconsole.errorand return a generic'Error retrieving SDK config'.Differences from #7547
common.jsfix covers three call sites in 24.05 vs two in master (returnRawwas removed/refactored on master).Test plan
/images/../../../etc/passwd(and via craftedthemecookie) — verifynext()is called instead ofsendFile\"><script>alert(1)</script>— verify it renders as text in the hidden input value, not as a script\"Error retrieving SDK config\", server logs the underlying errorreturnMessage/returnOutput/returnRaw— verify the log line no longer contains password/cookie material🤖 Generated with Claude Code