fix(make-pdf): three bugs that break browse resolution and temp-file writes - #2505
Open
lvthewah wants to merge 3 commits into
Open
fix(make-pdf): three bugs that break browse resolution and temp-file writes#2505lvthewah wants to merge 3 commits into
lvthewah wants to merge 3 commits into
Conversation
isExecutable() used only fs.accessSync(p, X_OK), which succeeds for directories because they carry the execute (traverse) bit. ./setup creates a skill directory at ~/.claude/skills/browse containing a SKILL.md symlink. resolveBrowseBin()'s third sibling candidate resolves to exactly that path, so it was returned as the browse "binary". Every subsequent browse invocation then failed with EACCES, surfacing as: [1/5] Checking browse binary... OK (/Users/me/.claude/skills/browse) [2/5] Launching Chromium... FAIL Guard with statSync(p).isFile() so only real files match. Co-Authored-By: claude-flow <ruv@ruv.net>
…list browseClient already documented this: v1.6.0.0 tightened --from-file validation (PR garrytan#1103), so os.tmpdir() on macOS (/var/folders/...) fails browse's validateReadPath. The PAYLOAD_TMP_DIR constant was introduced to fix it, but only writePayloadFile() used it. orchestrator.ts (default output, preview HTML, tmpFile) and setup.ts (smoke fixture and output) still used os.tmpdir(), so every one of those paths is rejected by browse: [4/5] Generating smoke-test PDF... FAILED: browse pdf exited 1: Path must be within: /private/tmp, ... Export PAYLOAD_TMP_DIR and use it at those five sites. This also makes the default output path match the documented behaviour in SKILL.md, which already says `$P generate letter.md` writes /tmp/letter.pdf. Drops the now-unused os imports from both files. Co-Authored-By: claude-flow <ruv@ruv.net>
browse's URL validation permits only http:, https: and file: schemes, so
the setup smoke test aborted before it ever reached the PDF stage:
[2/5] Launching Chromium... FAIL
Chromium failed to launch: browse newtab exited 1:
Blocked: scheme "about:" is not allowed.
Write a one-line blank HTML file under PAYLOAD_TMP_DIR (inside browse's
safe-dirs allowlist) and open that instead. Keeps the check network-free,
and removes the file in the existing finally block.
Co-Authored-By: claude-flow <ruv@ruv.net>
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
make-pdfis unusable on a stock global install:$P setupfails at step 1 or 2 and$P generatefails at the write stage. Three independent bugs, each with a one-line-ish fix. All three still reproduce onmainat v1.61.0.0.Found while using make-pdf for real work (a multi-page letter), per the CONTRIBUTING "fix gstack while doing your real work" flow.
The bugs
1.
isExecutable()resolves a directory as the browse binaryresolveBrowseBin()triespath.resolve(selfDir, "../browse")as a sibling candidate../setupcreates a skill directory at~/.claude/skills/browse(holding aSKILL.mdsymlink).isExecutable()only calledfs.accessSync(p, X_OK), which succeeds on directories because they carry the traverse bit:So make-pdf "found" a directory and every later browse call died:
Fix: guard with
statSync(p).isFile().2. Temp files land outside browse's safe-dirs allowlist
browseClient.tsalready documents this exactly, and already introducedPAYLOAD_TMP_DIRto solve it:But only
writePayloadFile()ever used the constant.orchestrator.ts(default output, preview HTML,tmpFile()) andsetup.ts(smoke fixture + output) still usedos.tmpdir(), so browse rejects them:Fix: export
PAYLOAD_TMP_DIR, use it at those five sites. Side benefit: the default output path now matches whatSKILL.mdalready documents ($P generate letter.md→/tmp/letter.pdf).3. Chromium smoke test uses a blocked URL scheme
browse permits only
http:,https:,file:.setup.tsopenedabout:blank:Fix: write a one-line blank HTML file under
PAYLOAD_TMP_DIRand open that. Network-free, cleaned up in the existingfinally.Verification
bun test make-pdf/test/→ 185 pass, 0 fail.Built the branch and ran the flow that was broken:
Also rendered a real 2,212-word / 8-page document end to end.
Notes
diagram-prepass.ts:294now declares its own duplicatePAYLOAD_TMP_DIR. Worth collapsing onto the exported one, but that felt like separate scope.os.tmpdir()only diverges from/tmpthere.