Files
codegraph/docs
danusha2345andClaude Opus 5.5 a565f215f1 fix(viewer): saved trails stay inside the project when a folder or trail file is a link
validatePathWithinRoot returned the lexical path whenever the path did
not exist yet (ENOENT). With .codegraph/ui a link to a folder outside
the project and no trails folder yet, the trails folder passed the
check, mkdir followed the link, and the trail was written outside the
project. The save still answered 403, but only because the list it
sends back re-checked the folder that now existed. The trails list also
joined each file name onto the checked folder and read it with statSync
and readFileSync, which follow links, so a trail file linking to a
trail-shaped file outside the project was listed and served.

validatePathWithinRoot now judges a missing path by its nearest
existing ancestor, and returns null when the root itself is missing.
The list reads every file through the same per-file check as a single
read, opens it with O_NOFOLLOW | O_NONBLOCK where the platform has
them, and checks the open file with fstat. Windows has neither flag;
there the per-file check is what refuses a planted link. A save
re-checks the folder after mkdir and writes its temp file under a
random name with flag wx and mode 0600. The trail author is cached per
project instead of per process, and a trail file that declares an
unknown format version is skipped.

Added on top of the contributor's change: the link tests also run on
Windows (a junction and a directory symlink at .codegraph/ui, a file
symlink in the trails folder), each test removes its own links before
deleting its folder, the helper gets a junction case and three
controls (an in-root link above a missing leaf, allowSymlinkEscape
above a missing leaf, a missing root), its doc comment names the new
missing-path rules, and the viewer changelog lines are reworded and
moved next to the other saved-trails line.

Validation: 8 tests fail on main and pass here (the helper below a
symlink and below a junction, a missing root, a save below a junction
and below a symlink, a linked trail file, the per-project author, the
format version). Through the real CLI (codegraph ui), main wrote the
trail outside the project through a junction and through a directory
symlink, and listed a linked outside file with its note; this branch
refused all three and wrote nothing outside. Graph dumps of express,
zod, excalidraw, flask and gin are byte-identical to main's, and 55 CLI
read commands and 45 MCP tool calls answer the same (codegraph_status
differs only by its last-indexed time). Index time is unchanged (gin
over 9 interleaved rounds: 2645 ms on main, 2687 ms here). Listing 200
saved trails, the list's cap, costs 108 ms on main and 236 ms here on
Windows; 10 trails cost 6 ms and 14 ms.

Original PR #1667 by @danusha2345.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 21:49:37 +00:00
..