Repository navigation
Gate green again: the adapter's errors are the adapter's, Bandit 1.13, one Hex for releases - #89
Merged
Merged
Conversation
An exception raised inside a call this transport makes into the adapter
(reading the body, sending the response, asking the protocol) is the
adapter's, and now goes back to it as itself, with its own stacktrace.
call/2's rescue used to answer any exception without a :plug_status as a
fault of this package: 500, -32603, and an error-level stacktrace in the
host's log.
Measured on Bandit 1.13.1, which rejects a mid-body HTTP/2 HEADERS frame
without END_STREAM as malformed (RFC 9113 8.1) by raising its own stream
error out of read_body. Before this change, the client got:
{":status", "500"} ... {"code":-32603,"message":"Internal error"}
** (Bandit.HTTP2.Errors.StreamError) Received trailers without END_STREAM
lib/beam_mcp/transport/http.ex:725: read_by_deadline/5
After: the adapter resets the stream with PROTOCOL_ERROR at the frame.
How it holds:
- adapter/1 is the one boundary. An exception raised in it is thrown,
tagged, past every rescue here, and re-raised by call/2. The adapter's
read timeout (status 408) is still answered by this package, since its
whole-body deadline is this package's contract.
- The host's code no longer runs anywhere a tag is passed on. dispatch/3
computes the answer (the core's handle_message and its encoding) under
the host-fault rescue and sends outside it. A host that throws the
private tag is just a host throw: -32603, with the request's id.
- fault_response/4's re-raise branch is removed. Nothing reaches it any
more except this package's own code, which is ours to answer.
- A census reads the compiled code. Every call into the adapter under
lib/ must sit inside adapter/1, with the population derived from
Plug.Conn's compiled forms (Plug.Conn.Adapter's callbacks, closed over
their callers). adapter/1 itself must catch and throw the tag.
Red first, against the transport before this change: the planted
adapters (a read with no status, a send) and the census failed, the
census listing exactly the seven call sites (http.ex :721 :725 :767
:1649 :1661 :1689 :1701). A host throwing the tag was red against an
earlier version of this fix, in which the host's code ran under the
tag's pass-through.
Mutants, test/beam_mcp/transport/, 173 tests; each one killed:
- adapter/1 re-raises: 10 failures.
- call/2 drops the tag: 6 failures.
- One call site unwrapped: 1 failure (the census).
- The 408 branch removed: 2 failures.
- The host's answer passes a tag on: 1 failure.
- fault_response/4 re-raises everything: 1 failure.
- The encode moved inside the boundary: 1 failure.
Signed-off-by: Ayla Croft <aylacroft@proton.me>
The optional requirement moves from {:bandit, "~> 1.5"} to
{:bandit, "~> 1.13"}, and this repository's lock moves bandit 1.12.5 to
1.13.1 (thousand_island 1.6.0, hpax 1.1.0). Both advisories are fixed in
1.13.0:
- EEF-CVE-2026-105659: HTTP/2 blocked-send deadlines reset on every
WINDOW_UPDATE.
- EEF-CVE-2026-105660: an HTTP/1 request target chooses conn.host and
conn.port.
The gate's audit step was failing on every pull request:
audit FAIL (Found packages with security advisories;)
bandit 1.12.5 - EEF-CVE-2026-105659 (HIGH)
bandit 1.12.5 - EEF-CVE-2026-105660 (MEDIUM)
A host that holds Bandit below 1.13 now gets Hex's conflict at
resolution (measured with a scratch host on "~> 1.12.0"). A stdio-only
host is unaffected: tools/probe_optional_deps.sh still passes.
On 1.13.1, the two tests that pinned the HTTP/2 HEADERS-without-
END_STREAM hold failed, as written to fail the day the adapter ended it.
They now assert what happens: a stream reset with PROTOCOL_ERROR at the
first such frame, and a second request on the same connection served.
The WINDOW_UPDATE hold is unchanged on 1.13.1 (the advisory fixed the
send side), and the connection deadline still bounds it.
A real-listener test covers a client that resets the socket before the
answer: no error line of this package's in the host's log. The threat
model, the README and the CHANGELOG say what changed.
Signed-off-by: Ayla Croft <aylacroft@proton.me>
Hex 2.5.2 (hex_core 0.20) sorts a package tarball's entries and its
metadata files list, so one commit has a different checksum under Hex
2.5.1 and under 2.5.2 or later. Measured with isolated MIX_HOMEs:
Hex 2.5.1: provenance_test 3 tests, 0 failures
Hex 2.5.2: 1 failure (the entry order at provenance_test.exs:135)
Hex 2.5.3: 1 failure
The publisher and CI must build with the same Hex, or the provenance
check fails at the next release:
- tools/hex-version names it (2.5.3).
- tools/release_tarball.sh refuses any other Hex, checked in the tree
that builds, with the command that installs the right one.
- The provenance workflow installs it with mix local.hex.
- The test derives the expected entry order from the Hex that built the
tarball, and checks that the script reads the pin file.
- docs/provenance.md says 0.10.1 and earlier reproduce only under Hex
2.5.1.
tools/sbom.sh moves to mix_sbom 0.12.0 (its published digest), which
reads the tools: :optional entry in mix.exs, so the one-line rewrite in
the scratch copy is removed and the tool reads the tree as tagged.
Signed-off-by: Ayla Croft <aylacroft@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
main's gate fails on every pull request for two outside reasons, and moving to the fixed Bandit exposed a defect in how the HTTP transport answers an adapter's own errors. This puts the gate back to green and fixes the defect.
What changes for a host
tools/hex-version). Hex 2.5.2 changed the tarball's entry order, so the publisher and CI must agree.Evidence
GATE_LEG=pinned GATE_AUDIT=require ./tools/gate.sh:Gate OK.