Skip to content

fix(dashboard): harden static path traversal checks#2027

Open
fallintoplace wants to merge 3 commits into
microsoft:mainfrom
fallintoplace:fix/dashboard-static-path-traversal
Open

fix(dashboard): harden static path traversal checks#2027
fallintoplace wants to merge 3 commits into
microsoft:mainfrom
fallintoplace:fix/dashboard-static-path-traversal

Conversation

@fallintoplace

Copy link
Copy Markdown
Contributor

Summary

  • Fix static file traversal guard in dashboard issue-monitor server.
  • Replace unsafe startsWith() root check with safe path.relative() containment check:
    • reject when rel.startsWith('..') or isAbsolute(rel)
  • Add regression test for sibling prefix traversal: /assets/../../<dist-name>-evil/secret.txt.

Testing

  • Not run in this change (per request).

Copilot AI review requested due to automatic review settings July 4, 2026 23:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens static-file path traversal protection in the contributor dashboard’s issue-monitor HTTP server by replacing a prefix-based root check with a path.relative() containment check, and adds a regression test that exercises a sibling-prefix traversal attempt.

Changes:

  • Replace resolved.startsWith(resolve(distDir)) with a relative(root, resolved) + .. / absolute-path rejection check for /assets/* requests.
  • Add a regression test that requests /assets/../../<dist-name>-evil/secret.txt via raw HTTP to avoid client-side URL normalization.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/apm-contributor-dashboard/.apm/extensions/issue-monitor/server-handler.mjs Updates the /assets/ static-file containment guard to use path.relative() instead of startsWith() path prefix checks.
packages/apm-contributor-dashboard/tests/server.test.mjs Adds a regression test for sibling-prefix traversal attempts against dist-evil-style paths.

Comment on lines +460 to +462
const resolved = resolve(root, normalize(urlPath.slice(1)));
const rel = relative(root, resolved);
if (rel.startsWith("..") || isAbsolute(rel)) {
Comment on lines +459 to 465
const root = resolve(distDir);
const resolved = resolve(root, normalize(urlPath.slice(1)));
const rel = relative(root, resolved);
if (rel.startsWith("..") || isAbsolute(rel)) {
res.writeHead(403); res.end("Forbidden"); return;
}
serveStatic(res, resolved);
@fallintoplace
fallintoplace force-pushed the fix/dashboard-static-path-traversal branch from c405c0a to aa94da1 Compare July 4, 2026 23:15
@fallintoplace fallintoplace changed the title Fix dashboard static path traversal containment fix(dashboard): harden static path traversal checks Jul 4, 2026
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