Repository navigation
fix(cli): protect HTML bundle inputs - #1690
Conversation
cd2ba80 to
2a00e58
Compare
Lorenzobattistela
left a comment
There was a problem hiding this comment.
Thanks for this. The direct and symlink collisions are refused now, and all gates pass merged onto main d194597 (repo 54/54, test 1663/1663, perf 124/124, ping 65/65 with your checks, safe 0 false rejects). A few things before merge:
-
A hard link to the page still gets overwritten. The guard compares realpath strings, and a hard link has a path of its own:
ln a/page.html h/page.html bend a/page.html -o hThis exits 0, and a/page.html now holds the bundle, so the source is lost. Comparing dev+ino from fs.statSync (when the output exists) catches symlinks, hard links and case-aliased paths in one check.
-
Only the entry page is checked. 1364d73 refuses an -o that resolves to any file the program reads. Here, an entry in the -o dir that is named like an output and points at a source .ts/.css/.bend (a stale symlink, say) is followed by Bun.write and overwritten. Could the check cover every file the build read, not just the page?
-
Dropping outdir loses Bun's directory check.
touch gf; bend g.html -o gfused to printFailed to create output directory "gf" is a file. Now it prints a rawENOTDIR: not a directory, open '.../gf/chunk-....js', and only after the full build. Please keep a clear error for a non-directory -o. Also, writes that fail partway (EACCES, a read-only page.html) leave a half-written bundle. -
The cause looks like Bun naming a symlinked entry after its target, which is where
dir/_.._/safe.htmlcomes from. Passing path_real(page) as the entrypoint (or settingroot) should give plain output names. The direct check then covers the symlink cases without the in-memory build and the second write loop. Could you try that? -
The "page symlink can bundle beside its link" check asserts the
_.._/safe.htmllayout. That layout predates this PR, but the check would fail a fix that puts the page at dir/.html, so please don't pin it. -
gates/ping.ts is maintained by Taelin, and gate changes need his sign-off, so we can't merge the new checks as they are. Please move them out of gates/ (into tests/, if a test there can drive the CLI), or leave them out and we'll raise it with him.
|
74b2324 to
c3bd746
Compare
Only the page keeps its name in a Bun bundle; chunks and assets are content-hashed, so the page is the one input an -o can overwrite by accident. Build from the page's real path (so the output name is known and a symlinked page no longer lands in _.._/), and refuse the build when dir/<page> is already the page by device and inode, which covers the direct, symlink and hard-link cases. Bun's outdir keeps writing and validating the directory, so the staging, rollback, metafile and config scans go, with their test; tests/io/bundle_page_input covers the cases. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
realpathSync ran before Bun.build, so `bend nope.html -o out` failed with a raw ENOENT lstat instead of Bun's ModuleNotFound entry error. Resolve the page with path_real and let same_file answer false for a missing file; the test covers it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The page keeps its real path's name and is guarded against -o overwrite; a missing page is left for Bun.build to report. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bend page.html -o <dir>can overwrite the page it bundles: directly (-ois the page's own directory), through a symlink, or through a hard link at<dir>/page.html.In a Bun bundle only the page keeps its own name; chunks, CSS and assets are content-hashed. So the page is the one input an
-ocan overwrite by accident.cli_bundlenow:path_real), so the output name is known and a symlinked page builds to<dir>/<target>.htmlinstead of<dir>/_.._/<target>.html;<dir>/<page>is already the page by device and inode (same_file), which covers the direct, symlink, hard-link and case-alias cases;outdirwriting, so a non-directory-oand a missing page still get Bun's own errors.Not covered on purpose: a link planted at an output path that points at another input (main behaves the same).
tests/io/bundle_page_inputcovers the refused cases, the symlinked build (its chunk runs) and the missing-page error; it fails on main.bend2/main.ts+172 ttok (11,871). Gates on ed186a4: repo 54/54, test 1683/1683, ping 63/63, perf 123/124, safe 0 false rejects.🤖 Generated with Claude Code