Conversation
Jessie-QingYu
left a comment
There was a problem hiding this comment.
Code Review: 🛑 REQUEST_CHANGES
The PR cleanly separates per-operation file-browser policies and preserves build artifacts in downloads. However, exposing dependency entries makes a symlink traversal gap reachable in shared-project views.
Verdict: REQUEST_CHANGES — The newly visible dependency tree exposes symbolic-link paths that the read handlers can follow outside an authorized shared project.
1 finding(s) posted as inline comments below.
| Severity | Category | File | Title |
|---|---|---|---|
| P1 | security | packages/core/src/lib/project-file-browser.ts |
Reject symlink traversal before exposing dependency entries |
| import type { FileBrowserScope } from "./file-browser-server.js"; | ||
|
|
||
| export const PROJECT_FILE_BROWSER_POLICY = { | ||
| treeIgnoredNames: [], |
There was a problem hiding this comment.
[P1] security — Reject symlink traversal before exposing dependency entries
Making node_modules tree-visible exposes package-link names in shared-project trees. createTreeHandler and createFileGetHandler resolve paths lexically and then use statSync/readFileSync, which follow those links; a request such as .../tree?path=projects/node_modules/linked-package (or a file beneath it) can enumerate or read an external target despite the share being scoped to one project. The new test only rejects the download endpoint. Reject symbolic-link components (or canonicalize and require the real path to remain under the scoped root) consistently for tree/read/asset/edit operations, and add a shared-route regression test for an external dependency symlink.
What this PR does
The Projects browser used the same ignore list for browsing, uploads, live updates, and folder downloads. That hid useful files and made visibility changes alter archive contents.
Folders named
build,coverage,dist, andnode_modulescan be browsed, edited, and uploaded. Folder downloads include build outputs and coverage reports, while skipping descendantnode_modulesentries. An explicitly selected dependency folder remains downloadable.Top-level folders with these names also resolve as projects, keeping the tree and dashboard consistent. Shared-project views use the same file policies within their authorized project.
Follows #379.
Design & Invariants
DESIGN.md. The existing project summary contract was checked for removal and remains applicable.Test plan
pnpm typecheckpnpm test:unitpnpm --filter @rome/core test src/api/routes/projects-files.test.ts src/api/routes/share.test.ts src/lib/file-browser-server.test.ts src/api/routes/memory-files.test.ts— 130 tests, including independent policy overrides and an external dependency symlink.pnpm lint:prosewith Vale 3.19.0, matching CI.git diff --check.pnpm dev:allandRome startedin the container log.distdashboard resolution.Host checks used a fresh install under Node 24.14.1 and pnpm 11.6.0. Nix is unavailable on this host. The dev stack uses offline local auth and a temporary Traefik landing-page port override because an existing Rome instance owns port 80. Browser folder selection did not attach files through the automation extension, so uploads were verified through the live multipart endpoint and regression tests.
Not in this PR