Skip to content

fix(infra): pin hyperframes ffmpeg by registry digest, not a rolling release asset - #1633

Merged
krishagel merged 2 commits into
devfrom
fix/hyperframes-ffmpeg-digest-pin
Aug 11, 2026
Merged

fix(infra): pin hyperframes ffmpeg by registry digest, not a rolling release asset#1633
krishagel merged 2 commits into
devfrom
fix/hyperframes-ffmpeg-digest-pin

Conversation

@krishagel

Copy link
Copy Markdown
Member

Summary

Unblocks the dev deploy. Building the HyperframesRender Lambda asset fails:

curl: (22) The requested URL returned error: 404
.../BtbN/FFmpeg-Builds/releases/download/autobuild-2026-07-15-14-01/ffmpeg-n7.1.5-...tar.xz

The comment above that block claimed the autobuild tag was immutable. It isn't — that assumption is the bug. BtbN keeps only a rolling window of autobuild releases and publishes no permanent version tags at all; the GitHub releases API returns latest plus autobuild-* and nothing else on every page. The oldest surviving autobuild right now is eight days old, so the July 15 pin was simply pruned.

Re-pinning to a newer autobuild would only reset the clock and break a deploy again in a few weeks, so this removes the expiring dependency instead.

Change

Download + sha256sumCOPY --from a registry image pinned by digest:

COPY --from=mwader/static-ffmpeg:7.1.1-amd64@sha256:6769881cc02c80d33e387750a8e144d162adfab2775e934dd97899261dda3a0c \
    /ffmpeg /ffprobe /opt/ffmpeg/

A registry digest is a content address that does not expire, so it keeps the verification strength the SHA256 gave while dropping the expiry. The tag stays alongside the digest for readability; the digest resolves. The whole curl/sha256sum/tar/chmod layer is gone — COPY preserves the source mode.

It also fits the requirement better than the original: built --disable-shared --enable-static with libx264/libx265, so nothing is dynamically loaded — not even glibc, which was BtbN's one remaining runtime dependency. The reason this block exists is that Debian's ffmpeg dynamically loads 40+ shared libraries and fails hyperframes' preflight inside the Lambda sandbox; a fully static binary has no such step.

Version note: 7.1.1 is the newest 7.1.x this publisher ships — a small patch step back from BtbN's n7.1.5. Deliberate: holding the ffmpeg 7 line hyperframes was validated against is lower risk in a deploy fix than jumping to 8.x/9.x.

Verification

Built the real image for linux/amd64 from the infra/ context rather than reasoning about it:

Check Result
Previously failing layer ✅ passes; full build completes
ffmpeg / ffprobe in the Debian base ✅ both report 7.1.1 (musl-static on glibc — worth proving, so a -version smoke check stays in the build)
Real libx264 encode inside the built image ✅ valid MP4; ffprobeh264,320,240
Exec bit without explicit chmod ✅ both -rwxr-xr-x

No CDK change needed: HyperframesRenderFunction passes no docker buildArgs, and nothing else in the repo referenced FFMPEG_BUILD / FFMPEG_ASSET / FFMPEG_SHA256.

Also corrected a sentence above the block that still described BtbN's linkage, which no longer describes what gets copied in.

Note on the same class of risk

AWS_LAMBDA_RIE_VERSION=v1.35 (line ~107) is pinned to a real GitHub release tag rather than a rolling autobuild, so it is not exposed to this failure mode. Left alone.

…release asset

The dev deploy failed building the HyperframesRender Lambda asset:

  curl: (22) The requested URL returned error: 404
  https://github.com/BtbN/FFmpeg-Builds/releases/download/
    autobuild-2026-07-15-14-01/ffmpeg-n7.1.5-2-g998de74adf-linux64-gpl-7.1.tar.xz

The comment above that block asserted the autobuild tag was immutable. It is not,
and that assumption is the whole bug. BtbN retains only a rolling window of
autobuild releases and publishes no permanent version tags at all -- confirmed
against the GitHub releases API, which returns `latest` plus `autobuild-*` and
nothing else across every page. At the time of this fix the oldest surviving
autobuild was eight days old, so the July 15 pin had simply been pruned. Any
autobuild pin rots on a timer; re-pinning to a newer one would only reset the
clock and break a deploy again in a few weeks.

Replaced the download + SHA256 check with a COPY --from a registry image pinned
by digest:

  mwader/static-ffmpeg:7.1.1-amd64@sha256:6769881cc02c80d33e387750a8e144d162adfab2775e934dd97899261dda3a0c

A registry digest is a content address that does not expire, so it keeps the
verification strength the SHA256 provided while removing the expiry. The tag is
kept alongside the digest for readability; the digest is what resolves. This also
deletes the curl/sha256sum/tar/chmod layer entirely -- COPY preserves the source
mode, so nothing needs chmod.

The replacement fits the requirement better than the original. It is built
--disable-shared --enable-static with libx264/libx265, so nothing is dynamically
loaded at all -- not even glibc, which was BtbN's one remaining runtime
dependency. The reason this block exists is that Debian's ffmpeg dynamically
loads 40+ shared libraries and fails hyperframes' preflight inside the Lambda
sandbox; a fully static binary has no such step.

Version note: 7.1.1 is the newest 7.1.x this publisher ships, a small patch step
back from BtbN's n7.1.5. Deliberate -- holding the ffmpeg 7 line that hyperframes
was validated against is lower risk in a deploy fix than moving to 8.x or 9.x.

Also corrected the sentence above that still described the BtbN build's linkage,
which no longer describes what is copied in.

Verified by building the real image for linux/amd64 from the infra/ context, not
by reasoning about it:
  - the previously failing layer now passes, and the build completes
  - /opt/ffmpeg/ffmpeg and /opt/ffmpeg/ffprobe both report 7.1.1 in the Debian
    base image (a musl-static binary on glibc is exactly the combination worth
    proving, so the build keeps a -version smoke check)
  - a real libx264 encode inside the built image produces a valid MP4;
    ffprobe reports h264,320,240
  - both binaries land executable without an explicit chmod

No CDK change: HyperframesRenderFunction passes no docker buildArgs, and nothing
else in the repository referenced FFMPEG_BUILD / FFMPEG_ASSET / FFMPEG_SHA256.
Copilot AI lite review requested due to automatic review settings August 11, 2026 04:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@claude

claude Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review

Solid, well-scoped fix — root cause (BtbN publishes no permanent tags, only a rolling ~2-3 week autobuild window) is correctly diagnosed and the digest pin is the right fix for the actual failure mode (link rot), not a band-aid re-pin that just resets the clock.

Strengths

  • Correct diagnosis, correct fix class. Re-pinning to a newer autobuild-* tag would have broken again in a few weeks; switching to a registry digest (@sha256:...) removes the expiry entirely while keeping the same content-address verification strength the old sha256sum -c check provided.
  • COPY --from=<image>@sha256:... is valid Docker syntax (works without a FROM ... AS stage, both classic builder and BuildKit) and is the standard way to vendor a binary from an external image — good choice over re-implementing curl/tar/checksum by hand.
  • Net risk reduction beyond fixing the 404: the new build is --disable-shared --enable-static, so not even glibc is dynamically loaded, which more directly addresses the original Lambda-sandbox preflight failure (feat(agent): psd-hyperframes skill — compose HTML/CSS/JS -> MP4 via dedicated render Lambda (port of heygen-com/hyperframes) #1175) than BtbN's build did.
  • Verified for real rather than reasoned about — actual linux/amd64 build, exec-bit check, and a real libx264 encode. The post-COPY ffmpeg -version/ffprobe -version sanity check is a good touch: it catches a musl-static-binary-on-glibc-base mismatch at build time instead of at cold start.
  • Confirmed via grep that no other file references the removed FFMPEG_BUILD/FFMPEG_ASSET/FFMPEG_SHA256 ARGs or needs a CDK buildArgs update — the change is fully self-contained to this one Dockerfile.
  • Comments are updated in place rather than left stale (the "BtbN...only glibc is dynamic" sentence was corrected to match what's now actually copied in).

Things worth a second look (non-blocking)

  1. Docker Hub as a new build-time dependency. This trades one external-availability risk (BtbN GitHub release pruning) for another (Docker Hub anonymous pull rate limits — 100 pulls/6h per IP for unauthenticated pulls). If cdk deploy/asset staging runs unauthenticated against Docker Hub from shared CI runner IPs, this could intermittently 429 the way the BtbN download intermittently 404'd, just less predictably. Worth confirming CI has a Docker Hub login (or is otherwise unaffected), since the digest pin doesn't protect against pull-rate throttling, only content drift.
  2. Third-party publisher trust. mwader/static-ffmpeg is a single-maintainer Docker Hub image, not an official/verified publisher. The digest pin means this specific build is what will always get copied in (no silent supply-chain swap), but the initial trust decision to depend on it isn't called out explicitly in the comment block the way the ffmpeg-version tradeoff is. A one-line note (e.g., "third-party publisher, pinned by digest so content can't drift under us") would help a future reader doing the same kind of audit this PR just did.
  3. No CI gate on the Docker build itself. This class of failure (an external asset silently disappearing) will still only surface at actual cdk deploy time, same as before — nothing in this PR changes that, and it's arguably out of scope, but worth a follow-up issue if there isn't already a periodic/CI build check for the Lambda image assets.

Other categories

  • Security: net improvement — same digest-based integrity guarantee as before, minus the expiry window, plus a fully static ffmpeg binary (smaller dynamic-loading attack surface). No secrets, no new IAM surface.
  • Performance: COPY --from avoids the curl/tar/sha256sum layer entirely, so this is a strict build-time win.
  • Test coverage: appropriately verified via manual image build/run for an infra Dockerfile change; no unit-testable surface here, consistent with how this file was tested previously.

Nice, tightly-scoped fix for an active deploy blocker. The two non-blocking notes above are about hardening the next failure mode, not objections to merging this.

Review asked for the trust decision to be stated as explicitly as the
ffmpeg-version tradeoff already was. Two points recorded where the next auditor
will look:

- mwader/static-ffmpeg is a third-party, single-maintainer image. The digest pin
  is what makes that acceptable: the exact bytes verified in this PR are the only
  bytes a later build can copy, so content cannot drift even if the tag moves.
- It adds no new availability domain. The base image already comes from Docker
  Hub, so a Hub outage or an unauthenticated pull-rate limit would have failed
  this build before this change too — the reviewer's rate-limit concern is real
  but pre-existing, not introduced here.

Comment-only.
@claude

claude Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review: fix(infra): pin hyperframes ffmpeg by registry digest, not a rolling release asset

Reviewed the diff to infra/hyperframes-render/Dockerfile (PR #1633).

Summary

Clean, well-justified fix. Replaces the BtbN autobuild-tag download (which has no permanent tags and rotates out after a few weeks — the actual cause of the dev deploy 404) with COPY --from=mwader/static-ffmpeg:7.1.1-amd64@sha256:..., a digest-pinned registry image. Digest pinning is a real fix for the root cause (rotating tags), not just a re-pin that would rot again on the same timer.

Code quality

  • The reasoning is unusually well documented directly in the Dockerfile comment (root cause, trust rationale, version-choice rationale), which is genuinely useful for the "next auditor" this will inevitably need. Matches the digest-pinning pattern already used elsewhere in this file (bun/uv/gh).
  • COPY --from=<image> without a preceding FROM ... AS name is valid multi-stage syntax (supported since Docker 17.05, not BuildKit-only), so no # syntax= directive is needed here — correctly used.
  • Dropping the explicit mkdir -p /opt/ffmpeg is safe; COPY creates the destination directory if missing.
  • Dropping the explicit chmod +x is safe if the source image ships the binaries executable, which the commit message says was verified by actually building the image — good, that's not something to take on faith.
  • Confirmed no dangling references elsewhere in the repo to the removed FFMPEG_BUILD / FFMPEG_ASSET / FFMPEG_SHA256 build args, and HyperframesRenderFunction (infra/lib/constructs/compute/hyperframes-render-function.ts) doesn't pass Docker build args, so this doesn't affect the CDK asset build path.

Bugs / correctness

None found. The new RUN ffmpeg -version && ffprobe -version smoke check is a reasonable replacement for the old post-extract sanity check and will fail the build loudly if the copied binaries don't actually run under Debian/glibc (the musl-static-on-glibc combination is exactly the thing worth proving, as the comment notes).

Performance

Slight improvement: removes the curl download + sha256sum + tar -xJ + chmod layer entirely in favor of a single COPY --from. Layer caching for this image build should be at least as good as before.

Security

  • Digest pinning is the correct mitigation here, and the added Dockerfile comment explicitly calls out that mwader/static-ffmpeg is a third-party, single-maintainer image and that the digest pin — not the tag — is what prevents content drift. Good that this tradeoff is written down rather than left implicit.
  • The "no new availability domain" point (Docker Hub was already a build-time dependency via the node:22-bookworm-slim base) is accurate and worth having on record for a future incident review.
  • No secrets or credentials involved; nothing else stands out.

Test coverage

  • Manual verification (documented in the commit message: real docker build, ffmpeg/ffprobe version + a real libx264 encode) is solid, but it isn't automated — ci.yml doesn't appear to build this container image, only run the JS/Python skill unit tests. That means the exact failure this PR fixes (an upstream artifact reference going stale) won't be caught again until the next deploy.
  • Not a blocker for this fix, but worth considering as a follow-up: a scheduled or PR-triggered CI job that does docker build (or at least a docker manifest inspect on the pinned digest) for infra/hyperframes-render would catch digest/tag rot or upstream image removal before it hits a deploy.

Nice fix overall — the root-cause analysis and the decision to move to digest pinning are both correct, and the tradeoffs are well documented for future readers.

@krishagel
krishagel merged commit f5bd648 into dev Aug 11, 2026
7 checks passed
@krishagel
krishagel deleted the fix/hyperframes-ffmpeg-digest-pin branch August 11, 2026 05:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants