Repository navigation
fix(aws-lambda): the handler ZIP installs its runtime from a committed lockfile with scripts off - #7485
Conversation
…d lockfile with scripts off build-zip.ts ran `npm install --no-package-lock` in the publish job, so transitive versions floated at release time and any dependency's install script ran beside the release credentials. The ZIP now runs `npm ci --ignore-scripts` from runtime-lock/<source>/package-lock.json (versions and integrity for every package), and the build fails if that lock disagrees with bun.lock instead of falling back to a range or "latest". `bun packages/aws-lambda/scripts/lock-runtime.ts` regenerates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
At 86f665a, the release ZIP staging now uses committed integrity-pinned npm locks and npm ci --ignore-scripts --omit=dev --omit=optional; the hosted Handler ZIP job actually built successfully with that path. I found no demonstrated missing native/install-script dependency in the current locks. One promised safety invariant remains false: lockMismatches compares only the direct package versions, and a transitive version already differs between the Bun and npm locks. Please clarify and separately maintain independent runtime locks, or make the claimed parity gate cover transitive drift as noted inline. The publish workflow calls build:zip for a fresh ZIP, but an existing attached ZIP retry reuses its artifact; no release run, Lambda runtime smoke or local build by me. Findings-only, not approval or release. — Jerrai
| const lock = JSON.parse(readFileSync(lockPath, "utf-8")) as { | ||
| packages: Record<string, { version?: string }>; | ||
| }; | ||
| return runtimePackages(source).flatMap((name) => { |
There was a problem hiding this comment.
This parity guard compares only the two direct package versions, not the dependency closure. There is already a mismatch at this head: Bun resolves modern-tar@0.8.4 (bun.lock:1881) while the committed Sparticuz npm lock ships modern-tar@0.8.6 (package-lock.json, node_modules/modern-tar). Both top-level checks pass. If Bun later updates a transitive dependency to address a security issue without changing puppeteer-core/Chromium versions, this gate will pass and the ZIP will keep shipping the prior npm-locked dependency. The npm lock still makes release builds reproducible and integrity-pinned; please either explicitly treat/runtime-audit these as independently maintained lock trees and narrow the parity claim, or enforce actual transitive parity with a regression for transitive-only drift. — Jerrai
… Renovate refreshes the rest The runtime lock's transitive tree is npm's own resolution, not bun.lock's (modern-tar 0.8.6 there vs 0.8.4 in bun.lock), so the parity claim now covers puppeteer-core and @sparticuz/chromium only. Renovate's weekly lockFileMaintenance refreshes the transitive tree; its direct-version bumps are off for these dirs because those follow bun.lock. — Rames Jusso Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Re-review at 50cae4a: my prior transitive-parity objection is addressed by making the two lock trees explicitly independent. runtimeLock.ts and build-zip.ts now promise/check only the direct Puppeteer/Chromium versions; the npm lock owns the complete runtime transitive tree. .github/renovate.json retains scheduled lock-file maintenance and vulnerability alerts while disabling direct-version bumps under these runtime-lock directories, and the author reports a scoped Renovate dry run. This is a coherent maintenance contract for the actually observed Bun/npm divergence. Hosted exact-head Handler ZIP and support tests completed successfully; I did not run a release or Lambda runtime smoke, and did not independently execute the Renovate dry run. No new code blocker found in this narrow successor; findings-only COMMENT, not approval or merge. — Jerrai
Superseded by code-clear successor review 5839243087 at 50cae4a; independent runtime lock maintenance contract now explicit. This dismisses the prior finding, not an approval.
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 0 important · 0 nits · head 50cae4a
The lockfile change holds up. npm ci --ignore-scripts is the only install in staging. Both locks carry integrity hashes for every package. No locked package has hasInstallScript. runtimeLock.test.ts catches drift from bun.lock in the required Test (support). Jerrai's transitive-parity finding is fixed.
- blocker: the required
Buildcheck is red because of this PR (jobs 129728675553 and 129733844129,verify:packed-manifests):@hyperframes/aws-lambda packed size 79651 bytes is over its budget of 78851 by more than 1%, 12 bytes over.files: ["scripts/"]now ships both locks, the runtime-lockpackage.jsons,runtimeLock.tsandlock-runtime.ts. Build passed at86f665a, and the comment-only50cae4atipped it over. Fix: add"!scripts/lock-runtime.ts"tofiles(it's a maintainer tool, like the already-excludedpin-handler-zip.ts), or raise the budget inscripts/package-size-budgets.jsonwith a reason. KeepruntimeLock.tsandruntime-lock/, becausebuild-zip.tsreads them.
Notes
Tests on windows-latestfailed on engine-cli timeouts (parallelWorkerBrowsers,reject-unknown-flags,cloud/render --dry-run) in files this PR doesn't touch. Other Windows runs that hour were green, so rerun it after the fix.- Pre-existing, follow-up:
publish.yml:158bun install --frozen-lockfilestill runs bun's default-trusted install scripts in the release job, and the ZIP's ffmpeg comes fromffmpeg-static's postinstall download with no lock hash. The body reads as if the "scripts next to release credentials" concern is fully closed.
— Genesis
…the package Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Narrow re-review at 79f53be: the only new change excludes maintainer-only scripts/lock-runtime.ts from the published @hyperframes/aws-lambda package's files list while leaving the runtime-lock data and runtimeLock.ts available to the ZIP builder. This directly addresses the earlier packed-manifest budget regression; the exact-head hosted Handler ZIP job passed, and Build had completed its build step but was still running verify:packed-manifests at review time. No new source blocker found in this one-line successor; the prior independent npm lock/update contract remains as reviewed. I did not run npm pack, Lambda runtime smoke or a release locally. Findings-only COMMENT, not approval or merge. — Jerrai
…fy its hash before release The handler zip build runs dependency install and bundling code. It moves out of the publish job into its own job with `contents: read`, no secrets and no persisted git credentials. The publish job downloads the artifact, checks its sha256 against the build job's output, then pins and attaches it as before. A retried run still reuses the zip already on the release. Refs #7485 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fy its hash before release (heygen-com#7495) * ci(publish): build the Lambda handler zip in a read-only job and verify its hash before release The handler zip build runs dependency install and bundling code. It moves out of the publish job into its own job with `contents: read`, no secrets and no persisted git credentials. The publish job downloads the artifact, checks its sha256 against the build job's output, then pins and attaches it as before. A retried run still reuses the zip already on the release. Refs heygen-com#7485 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ci): cover the read-only Lambda zip build job and the pin step's hash check The publish workflow test still looked for the old "Build Lambda handler zip" step. It now checks the build job's read-only permissions and the publish job's dependency on it, and runs the pin step for the retry, matching-hash, mismatched-hash and empty-hash cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
What
The Lambda handler ZIP's
node_modulesnow come from a committed lockfile (packages/aws-lambda/scripts/runtime-lock/<source>/package-lock.json, with version and integrity for every package). They are installed withnpm ci --ignore-scripts. The build fails if the lock'spuppeteer-coreor@sparticuz/chromiumversion disagrees withbun.lock. The transitive tree is the lock's own (npm resolves it, so it can differ frombun.lock), and Renovate's weekly lock-file maintenance keeps it current.Why
build-zip.tsstaged the runtime withnpm install --no-package-lock:puppeteer-coreand@sparticuz/chromiumwere pinned, and transitive dependencies floated at release time. Two builds of the same commit could ship different code.readDepVersionsilently fell back to the package.json range, or tolatest, ifbun.lock's format changed.publish.yml's release job, next to its credentials.Related work
Hardening from an internal security scan. No public issue.
How
scripts/runtimeLock.ts:bun.lock.assertRuntimeLockCurrentrefuses a committed lock whose top-level versions differ frombun.lock. In a published package there is nobun.lock, so the committed lock is used as is.build-zip.ts:--sourceinto staging and runsnpm ci --ignore-scripts --omit=dev --omit=optional.readDepVersionand itslatestfallback are gone.scripts/lock-runtime.ts: regenerates both locks frombun.lock. Run it after bumpingpuppeteer-coreor@sparticuz/chromium..github/renovate.json: for the tworuntime-lockdirs, Renovate's direct-version bumps are off (those followbun.lockthroughlock-runtime.ts), and its weeklylockFileMaintenancerefreshes the transitive tree. A localrenovate --platform=local --dry-run=lookupscoped to those dirs disabled the 3 direct bumps and kept only therenovate/lock-file-maintenancebranch.lambda-arm64-image.ymlnow also runs its Handler ZIP job when the lock orruntimeLock.tschanges.--ignore-scriptsis safe here: a trial install of both trees found no package with apreinstall,installorpostinstallscript.Test plan
Real build: ran
bun run build, thenbun run --cwd packages/aws-lambda build:zip, on this branch.npm ciadded 44 packages fromruntime-lock/sparticuzand the ZIP built: 242.8 MiB unzipped, 123.9 MiB zipped.node_modulespackages have exactly the versions today's floatingnpm installof the same two pins resolves, so nothing that ships changes now. It just can't drift later.package-lock.jsonisn't in the ZIP.runtimeLock.test.ts:bun.lock.bun.lockthat bumpspuppeteer-corewithout re-locking is reported as stale. 3 pass.build-zip.test.tsstill passes.oxlint,oxfmtand the pre-commitfallowgate are clean.Unit tests added/updated
Manual testing performed
Documentation updated (if applicable)
Comments follow CONTRIBUTING.md "Comments"
— Rames Jusso
🤖 Generated with Claude Code