Skip to content

ESD-1629: emit WASM artifact integrity hashes from the publish workflow#519

Open
Phil-Browne wants to merge 5 commits into
mainfrom
esd-1629-wasm-publish-hashes
Open

ESD-1629: emit WASM artifact integrity hashes from the publish workflow#519
Phil-Browne wants to merge 5 commits into
mainfrom
esd-1629-wasm-publish-hashes

Conversation

@Phil-Browne

Copy link
Copy Markdown
Contributor

Extends the WASM publish workflow to emit integrity reference values and attest the artifact, so the Portal can verify the megaport.wasm it loads from media.megaport.com is the one we published (SEC-8095).

  • New "Compute integrity hashes" step: SHA-256 (hex) of the uncompressed megaport.wasm and the sha384-<base64> SRI of wasm_exec.js.
  • The step summary now shows both values under the version prefix, ready to copy into the Portal WASM-loader config per release.
  • Adds an actions/attest-build-provenance step (SHA-pinned, same version as release.yaml) for megaport.wasm, plus attestations: write on the job.

The hash is taken over the pre-brotli bytes, i.e. what the browser sees after the Content-Encoding: br decode, not the .br object. Verifying the deployed artifact with gh attestation verify must therefore be done against the br-decoded bytes, not the raw CDN object.

No change to the S3 publish, cache-control, or any Portal/web-monorepo code.

Relates to SEC-8095. Blocks the Portal WASM-loader integrity check.

Compute the SHA-256 (hex) of the uncompressed megaport.wasm and the
sha384 SRI of wasm_exec.js, surface both in the run's step summary
labeled with the version prefix, and attest megaport.wasm with build
provenance. The hashes feed the Portal's client-side WASM integrity
check (SEC-8095); they are taken over the pre-brotli bytes the browser
sees after the Content-Encoding: br decode, never the .br object.
Copilot AI review requested due to automatic review settings July 10, 2026 14:53
@Phil-Browne Phil-Browne requested review from a team and penzeliz-megaport as code owners July 10, 2026 14:53
@Phil-Browne Phil-Browne requested a review from ianb-mp July 10, 2026 14:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 enhances the manual WASM publish GitHub Actions workflow by generating integrity reference values and adding a build-provenance attestation for the published WebAssembly artifact, enabling downstream consumers (e.g., the Portal) to verify they are loading the intended megaport.wasm release.

Changes:

  • Adds an explicit “Compute integrity hashes” step to emit a SHA-256 (hex) for the uncompressed megaport.wasm and an SRI (sha384-<base64>) value for wasm_exec.js.
  • Adds a pinned actions/attest-build-provenance step and the required attestations: write permission for provenance attestation.
  • Extends the workflow step summary to include copy/paste-ready integrity values scoped to the published version.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.29%. Comparing base (dee5b8d) to head (7e4722e).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #519   +/-   ##
=======================================
  Coverage   79.29%   79.29%           
=======================================
  Files         193      193           
  Lines       18683    18683           
=======================================
  Hits        14814    14814           
  Misses       2820     2820           
  Partials     1049     1049           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@penzeliz-megaport

Copy link
Copy Markdown
Collaborator

Reviewed for the SEC-8095 audit. The workflow is correct and CI is green. Nothing below blocks merge; they are hardening and audit notes.

Verified

  • wasmcompress only reads megaport.wasm and writes .br/.gz beside it (temp file + atomic rename), so hashing the uncompressed file after the compress step is sound. No step between the hash and the upload rebuilds those bytes.
  • The pinned actions/attest-build-provenance@e8998f94 resolves to upstream v2.4.0 and matches the pin in release.yaml.
  • SHA-256 over the uncompressed wasm matches what the browser gets: fetch() brotli-decodes transparently, so the Portal's crypto.subtle.digest('SHA-256', ...) will agree. openssl base64 -A emits standard base64, which SRI requires.

Findings (non-blocking)

  1. The attestation subject is the uncompressed wasm, but the object served at .../megaport.wasm is the brotli bytes. gh attestation verify against a raw download of the CDN object fails on a digest mismatch unless you br-decode first. That is in the PR description but not in the workflow, so whoever chases a failed attestation later won't see it. Add a comment at the attest step and the exact verify recipe.
  2. The hash and SRI exist only in the run's step summary. Publish a megaport.wasm.sha256 sidecar or an integrity.json manifest under the version prefix so the values are re-verifiable without re-hashing.
  3. For the audit record: the attestation proves origin, not approval. The deploy role trusts the whole repo and there is no environment: reviewer gate, so anyone with write access can publish and attest arbitrary bytes. The runtime guarantee depends on the Portal's hash check plus correct manual transcription of the hash each release, neither of which lives in this repo. Both belong in the audit scope.

Minor: the wasm SHA-256-hex vs js SHA-384-SRI split is intentional (streaming wasm instantiation has no integrity attribute); a one-line comment would stop it reading as an oversight.

@penzeliz-megaport penzeliz-megaport left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed for correctness; findings noted in comments are non-blocking. LGTM.

Adds the attestation verify recipe and a note on the wasm/br subject
mismatch, an integrity.json sidecar so the hashes are re-verifiable
without re-hashing, a comment explaining the hex-vs-SRI split, and an
audit-scope note that attestation proves origin, not approval.
@Phil-Browne

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review. Verified the three points independently:

  • wasmcompress opens the source read-only and writes .br/.gz via temp-file-then-rename, so it never mutates megaport.wasm before or after hashing.
  • The attest-build-provenance pin matches release.yaml exactly (both resolve to v2.4.0).
  • Confirmed the browser sees the uncompressed bytes after brotli decode, so the hash lines up with crypto.subtle.digest.

Addressed the four hardening notes:

  • Added the exact gh attestation verify recipe (br-decode first) as a comment on the attest step.
  • Added a Write integrity manifest step publishing integrity.json alongside the site, so the hash/SRI values are re-verifiable from the CDN without re-hashing or relying on the step summary (which Actions eventually expires).
  • Added a comment explaining the hex-vs-SRI split (streaming wasm instantiation has no integrity attribute).
  • Added an INTEGRITY (SEC-8095) note to the workflow header capturing that attestation proves origin, not approval, and that the Portal's hash check plus correct manual transcription each release are out of this repo's control.

Left the environment: production reviewer gate out of scope here since it needs a repo admin to create the environment first; that's already flagged in the existing SAFETY comment as a separate follow-up.

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.

3 participants