Repository navigation
refactor(cli): templates pull unpacks the verified pack from memory - #7084
Conversation
The pack was written to a temporary file before tar read it. tar now reads the checked bytes on stdin, so nothing downloaded is written to disk before it is unpacked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jrusso1020
left a comment
There was a problem hiding this comment.
Reviewed at 8d40a1ad1baae6070281aecb7ee271b640b20b51.
The verified buffer feeds both tar invocations (packages/cli/src/commands/templates.ts:87–91,106), so listing and extraction see the same bytes without an intermediate archive file. Pinned length/SHA checks still precede tar, path validation still precedes extraction, and the staging directory remains inside try/finally cleanup with publication only after extraction succeeds (:81–83,100–110). No new blocker found in the one-file refactor.
Validation: full root bun run build passed. bun run --cwd packages/cli test src/commands/templates.test.ts reports 8 passed; oxlint reports zero errors/warnings and oxfmt --check passes. The suite executes real tar for ordinary extraction, unsafe parent paths, hash refusal, auth/plan refusal and existing destinations. Separate exact-source controls extract only assertSafeEntries/unpack and inject Node built-ins (they bypass HTTP/auth/hash checks): 11 scenarios × base/head × Node/Bun = 44 invocations. Ordinary and synthetic 140,711,403-byte archives pass; corrupt/truncated input, unsafe paths and an archive that writes a then fails extracting a/b leave no destination or staging directories. These include actual extraction failure, rather than only list-time refusal. I inspected the probe and reran the 22 Node invocations. The synthetic large archive is not the private production pack.
Bounded behavior difference: at templates.ts:88–92, Node can report EPIPE if tar exits successfully before consuming large store-compressed trailing padding or concatenated gzip members. The file-input base succeeds on those synthetic cases; Bun did not show that difference. No evidence shows that layout in any of the five pinned packs, so I do not treat it as a demonstrated shipped regression. The parity claim is limited to the exercised ordinary-pack cases; future pack publication should retain an stdin extraction check.
Limits: local Node 22.22.3 / GNU tar 1.30 only; no Windows run or live production pull by me; the author's real 140 MB pack result is not my reproduction. This review does not claim a general audit of tar/archive trust or re-verify plan enforcement.
Need: yes · Size: one-file refactor · Reuse: existing verified buffer and Node execFileSync input · Simpler: removes temporary archive write · Structure: fine
Risk: low — narrow change to the pinned-pack workflow, with Windows execution not independently verified.
Verdict: APPROVE
Reasoning: Both tar calls consume the verified bytes and preserve the exercised validation/publication/cleanup behavior.
— hf-review
What
hyperframes templates pullunpacks the downloaded pack from memory:tarreads the checked bytes on stdin for both the path check and the extraction. The temporarytemplate.tar.gzis gone.Why
CodeQL flagged the write of downloaded bytes to disk (
js/http-to-file-access, alert 1273). It was a false positive, since the bytes are checked against the pinned size and sha256 first, and was dismissed so #6842 could land. This removes the write so the pattern is not there to flag.Related work
Follows #6842.
How
assertSafeEntriesrunstar -tzf -with the pack asinput.unpackrunstar -xzf - -C <staging> --no-same-ownerwith the sameinput, then moves the folder into place as before.Test plan
templates.test.ts: 8 passed (pinned pull, 402/401/503, hash mismatch, unsafe archive path, existing destination, cleanup on refusal).-f -).Size
One file, 6 added and 7 removed lines.
🤖 Generated with Claude Code