mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-25 03:49:59 +08:00
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>