Skip to content

Verify FFmpeg against a pinned SHA-256 from the signed release tarball - #82

Merged
mormegil6 merged 3 commits into
EnvelopSound:masterfrom
mormegil6:harden-ffmpeg-signed-tarball
Aug 20, 2026
Merged

Verify FFmpeg against a pinned SHA-256 from the signed release tarball#82
mormegil6 merged 3 commits into
EnvelopSound:masterfrom
mormegil6:harden-ffmpeg-signed-tarball

Conversation

@mormegil6

Copy link
Copy Markdown
Collaborator

A focused follow-up to #81. That PR moved the build to the upstream 7.1 source but fetched it from GitHub's /archive/refs/tags/ URL, a tarball generated on demand whose bytes are not stable (GitHub has changed archive compression before), so there is nothing a checksum could meaningfully pin against. This switches the source to the ffmpeg.org release artifact and verifies it against a pinned SHA-256 before anything is extracted or compiled.

What changes:

  • Source: https://ffmpeg.org/releases/ffmpeg-7.1.tar.xz instead of the GitHub archive URL. This is the signed, immutable release tarball, the same artifact ffmpeg.org publishes a GPG signature for.
  • Verification: the download is checked against a pinned SHA-256 (echo "<hash> <file>" | sha256sum -c -) before extraction. A mismatch aborts the build rather than silently compiling unexpected source. The pinned hash is the one FFmpeg's release signing key (FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8) signs for 7.1; I verified that signature against the key before hardcoding the hash.
  • Container: the release is .tar.xz, so the build adds xz to the Alpine build deps and decompresses with xz -dc | tar. The extract directory is lowercase ffmpeg-7.1 (release convention) rather than FFmpeg-n7.1 (GitHub archive convention), updated in the two cd references and the one commented-out COPY.

FFMPEG_VERSION goes n7.1 -> 7.1 to match the release naming, and a FFMPEG_SHA256 arg holds the pin. Everything downstream is unchanged: the DASH suggestedPresentationDelay floor sed and its build-time post-check, the configure flags, the compile. It is the same 7.1 source, fetched from the release channel and verified.

One maintenance note for whoever bumps ffmpeg next: the pin is version-locked, so a change to FFMPEG_VERSION must come with a matching FFMPEG_SHA256, or the build stops at the checksum step. That is the guard doing its job rather than a regression, but it is worth stating so the failure is expected rather than surprising.

Verified on real builds of this image, amd64 and a native arm64 build on a Raspberry Pi 4: the checksum check passes on both arches (ffmpeg-7.1.tar.xz: OK), the .tar.xz decompresses and the image builds to completion, and the SPD-floor patch still applies byte-for-byte. A deliberately corrupted pin was also tested: the build fails at the sha256sum -c step with 1 computed checksum did NOT match, before the download is extracted and before ffmpeg is compiled, and no image is produced.

Follow-up to EnvelopSound#81. That PR built from the upstream n7.1 source but fetched
it from GitHub's /archive/refs/tags/ URL, a tarball generated on demand
whose bytes are not stable (GitHub has changed archive compression
before), so there is nothing a checksum can meaningfully pin against.
Switch the source to the ffmpeg.org release artifact and verify it against
a pinned SHA-256 before extracting or compiling.

- Source: ffmpeg.org/releases/ffmpeg-7.1.tar.xz, the signed immutable
  release tarball, in place of the GitHub archive URL.
- Verify: sha256sum -c against a pinned hash aborts the build on mismatch
  rather than compiling unexpected source. The hash is the one FFmpeg's
  release signing key (FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8)
  signs for 7.1.
- Container: the release is .tar.xz, so add xz to the build deps and
  decompress with xz -dc | tar. The extract dir is lowercase ffmpeg-7.1
  (the release convention), updated in its references.

FFMPEG_VERSION goes n7.1 -> 7.1 to match the release naming; a
FFMPEG_SHA256 arg holds the pin. The DASH suggestedPresentationDelay floor
sed and everything downstream are unchanged: same 7.1 source, fetched from
the release channel and verified.
n9.0 removed the only PCE config that can encode a layout above 8 channels,
which breaks the 16-ch AAC contribution leg at runtime while still building
clean. Record that at the line someone would edit to bump the version.
Copilot AI lite review requested due to automatic review settings August 20, 2026 15:48

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.

Pull request overview

This PR improves the FFmpeg build supply-chain integrity by switching from GitHub’s dynamically-generated tag archives to FFmpeg’s official release tarball and verifying the download against a pinned SHA-256 before extraction/compilation.

Changes:

  • Switch FFmpeg source download to https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz.
  • Add a pinned checksum (FFMPEG_SHA256) and verify via sha256sum -c prior to extraction.
  • Add xz to build dependencies and update paths to match the release tarball’s ffmpeg-${FFMPEG_VERSION} directory naming.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Dockerfile Outdated
Comment on lines +43 to +51
# Do not bump past n8.1 without re-checking 16-channel AAC encoding. n9.0
# removed AV_CHANNEL_LAYOUT_HEXADECAGONAL from aac_pce_configs[] in
# libavcodec/aacenc.c (c92c6cbf19), and with it the only PCE config able to
# encode any layout above 8 channels. The RTMP contribution leg carries 16-ch
# AAC with a PCE from OBS Music Edition, so on n9.0 that leg dies at encoder
# init with "Unsupported channel layout". Note this is a RUNTIME failure, not
# a build failure: the image still builds clean and only breaks when a
# 16-channel stream actually arrives. Verified present at n7.0 through n8.1,
# absent at n9.0 and master.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch, fixed in cc72b80. The comment now uses release numbers throughout, matching FFMPEG_VERSION and the ffmpeg.org tarball, and names the n-prefixed git tag form once so both are unambiguous.

The comment sat above FFMPEG_VERSION, which now carries a release name (7.1),
but described the ceiling in git-tag form (n8.1, n9.0). Someone bumping the
variable would write 8.1, not n8.1, so the two notations did not line up.
State the releases, and name the tag form once so both are unambiguous.
@mormegil6
mormegil6 merged commit e9065f6 into EnvelopSound:master Aug 20, 2026
4 checks passed
mormegil6 added a commit to mormegil6/Earshot that referenced this pull request Aug 20, 2026
@mormegil6
mormegil6 deleted the harden-ffmpeg-signed-tarball branch August 20, 2026 16:07
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