Skip to content

Every leg at its line's patched OTP floor; the box leg on aarch64 - #18

Merged
HackTuah merged 2 commits into
mainfrom
ci/otp-floor-and-arm64
Oct 20, 2026
Merged

HackTuah merged 2 commits into
mainfrom
ci/otp-floor-and-arm64

Conversation

@HackTuah

Copy link
Copy Markdown
Member

This change is CI and pinning only. Nothing a consumer of the package can hit changes, and mix.exs's supported floor stays OTP 27. It is the signer's half of beam_mcp's #90.

CVE-2026-55737 (heap corruption in binary_to_term/1) is fixed in OTP 27.3.4.15, 28.5.0.4 and 29.0.4. .tool-versions pinned 28.1.1, below its floor, and no leg asserted a patched release.

What changes

  • Every leg is held to its line's patched floor. tools/otp-floors and tools/otp_floor.sh are copies of beam_mcp's. Each leg runs the script right after setup-beam and prints the pair it got, the OpenSSL :crypto is linked to, and whether it offers ML-DSA-87 (printed, not asserted).
  • A fourth leg, box: OTP 28.5.0.8 with Elixir 1.20.4, exact versions, on ubuntu-24.04-arm. These are the versions and the architecture a fielded edge box runs. Minutes for a public repository are free on both architectures.
  • .tool-versions pins erlang 28.5.0.8.
  • Docs say four legs, and GOVERNANCE says six required checks.

Evidence

  • tools/otp_floor.sh: OTP 28.1.1 is refused; 28.5.0.8 and 29.1 pass.
  • The test job's steps pass locally on OTP 28.5.0.8 with Elixir 1.18.4 and with 1.20.4.
  • reuse lint: compliant.

Not yet measured

  • The box leg on aarch64. This run is its first measurement.

Before merging

  • The ruleset on main names its required checks one by one. "test (OTP 28.5.0.8, Elixir 1.20.4, box)" has to be added to it, or the box leg is not required and GOVERNANCE's "six checks" is not true.

CVE-2026-55737 (heap corruption in binary_to_term/1 decoding
LARGE_TUPLE_EXT) is fixed in OTP 27.3.4.15, 28.5.0.4 and 29.0.4.
.tool-versions pinned 28.1.1, below its line's floor, and no CI leg
asserted a patched release.

- tools/otp-floors and tools/otp_floor.sh are copies of beam_mcp's: the
  floor of each line, and a script that reads the running release's
  OTP_VERSION file and refuses a runtime below its line's floor. Every CI
  leg runs it right after setup-beam, and prints the installed pair,
  the OpenSSL that :crypto is linked to, and whether it offers ML-DSA-87
  (printed, not asserted: an ML-DSA signer needs to know which legs can
  run it).
- A fourth leg, "box", runs OTP 28.5.0.8 with Elixir 1.20.4
  (version-type: strict) on ubuntu-24.04-arm: the versions and the
  architecture a fielded edge box runs. Minutes for a public repository
  are free on both architectures.
- .tool-versions: erlang 28.5.0.8.
- CONTRIBUTING, GOVERNANCE and docs/assurance-case.md say four legs;
  GOVERNANCE says six required checks, which holds once the box leg's
  name is added to the ruleset.

Measured locally:

    28.1.1:   below the patched floor 28.5.0.4 for line 28 (CVE-2026-55737); refused
    28.5.0.8: at or above the patched floor 28.5.0.4 for line 28
    29.1:     at or above the patched floor 29.0.4 for line 29

The test job's steps (floor, format, compile with warnings as errors,
Credo, Hex audit, tests) pass on OTP 28.5.0.8 with Elixir 1.18.4 and
with Elixir 1.20.4, on x86_64. The box leg has not run on aarch64 yet;
this pull request's first CI run is that measurement.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
The box leg ran on ubuntu-24.04-arm, where builds.hex.pm's OTP links
the runner's OpenSSL 3.0.13 and :crypto offers no ML-DSA. The image a
fielded edge box runs pins OpenSSL 3.5 or later, the line ML-DSA needs,
so the leg did not run the runtime the box runs, and an ML-DSA-87
signer had no leg in this repository that could exercise it.

- The box leg runs on ubuntu-26.04-arm. GitHub's 26.04 runner images
  ship OpenSSL 3.5.5 (public preview; ubuntu-latest moves to 26.04 in
  November 2026), and builds.hex.pm publishes OTP 28.5.0.8 for
  ubuntu-26.04 on arm64 and amd64.
- tools/mldsa_offered.sh prints the OpenSSL that :crypto is linked to
  and whether it offers ML-DSA-87, on every leg. With MLDSA_REQUIRED=1,
  which only the box leg sets, a runtime without it is refused by name,
  so the leg cannot pass on a runtime that cannot sign with it.
- GOVERNANCE says the box leg runs over an OpenSSL that offers
  ML-DSA-87.

The check name is unchanged, so the ruleset entry the box leg needs is
the same one.

Measured locally (tools/mldsa_offered.sh):

    OTP 28.5.0.8 over OpenSSL 3.0.13, required:  offered false; refused (exit 1)
    OTP 29.1 over OpenSSL 3.0.13, required:      offered false; refused (exit 1)
    OTP 28.5.0.8 over OpenSSL 3.5.9, required:   offered true (exit 0)
    not required, on each:                       printed only (exit 0)

builds.hex.pm's OTP-28.5.0.8 for ubuntu-26.04 amd64, with its sha256
checked against builds.txt and run in ubuntu:26.04, is linked to
OpenSSL 3.5.5 and offers mldsa87; generate, sign and verify succeed.
The arm64 build has not run yet; this push's CI run is that
measurement.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
@HackTuah
HackTuah merged commit bb62ba6 into main Oct 20, 2026
8 checks passed
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.

1 participant