Over HTTP/2 the appliance returns the origin's bytes unmodified. No URL rewriting, no injected script, no auction. The page renders correctly and none of the product is in it.
extract_request_host in crates/trusted-server-core/src/http_util.rs (lines 166 to 184 at 0f8b44dc0) reads Forwarded, then X-Forwarded-Host, then Host, and defaults to empty at line 182. It never consults the request URI authority. HTTP/2 carries the authority in the :authority pseudo-header and clients are not required to send Host at all, so the host is empty on every HTTP/2 request.
An empty host takes the unmodified branch at crates/trusted-server-core/src/publisher.rs line 4838. The only trace is one warning:
Empty request host — returning processable content unmodified (Content-Type: '{}', status: {}). Check proxy Host header.
Browsers negotiate HTTP/2 whenever the server terminates TLS. So this is ordinary production HTTPS traffic rather than an edge case, and it is invisible from outside because the page itself is correct.
How it was found
A live publisher site served through a local deployment with TLS terminated at the server. curl saw the page rewritten and the script injected. Chrome, against the same server at the same moment, saw the origin page untouched. The warning above was in the log throughout.
One trap worth passing on. curl --http2 still sends a Host header, so it does not reproduce the fault. Only a client that omits Host does, which is what a browser does.
Suggested fix
Fall back to the URI authority after Host, so an explicit header still wins.
A branch is ready at fix/http2-authority-host. One commit, one file, 48 lines, based on 0f8b44dc0, with two tests, one of them asserting that an explicit Host beats the authority. It merges cleanly against main and passes cargo clippy --all-targets -- -D warnings, cargo fmt --check and the http_util unit tests. Happy to open it as a pull request if that is useful.
Written with AI assistance and checked against the source at 0f8b44dc0. Worth a human review before acting on it.
Over HTTP/2 the appliance returns the origin's bytes unmodified. No URL rewriting, no injected script, no auction. The page renders correctly and none of the product is in it.
extract_request_hostincrates/trusted-server-core/src/http_util.rs(lines 166 to 184 at0f8b44dc0) readsForwarded, thenX-Forwarded-Host, thenHost, and defaults to empty at line 182. It never consults the request URI authority. HTTP/2 carries the authority in the:authoritypseudo-header and clients are not required to sendHostat all, so the host is empty on every HTTP/2 request.An empty host takes the unmodified branch at
crates/trusted-server-core/src/publisher.rsline 4838. The only trace is one warning:Browsers negotiate HTTP/2 whenever the server terminates TLS. So this is ordinary production HTTPS traffic rather than an edge case, and it is invisible from outside because the page itself is correct.
How it was found
A live publisher site served through a local deployment with TLS terminated at the server.
curlsaw the page rewritten and the script injected. Chrome, against the same server at the same moment, saw the origin page untouched. The warning above was in the log throughout.One trap worth passing on.
curl --http2still sends aHostheader, so it does not reproduce the fault. Only a client that omitsHostdoes, which is what a browser does.Suggested fix
Fall back to the URI authority after
Host, so an explicit header still wins.A branch is ready at
fix/http2-authority-host. One commit, one file, 48 lines, based on0f8b44dc0, with two tests, one of them asserting that an explicitHostbeats the authority. It merges cleanly againstmainand passescargo clippy --all-targets -- -D warnings,cargo fmt --checkand thehttp_utilunit tests. Happy to open it as a pull request if that is useful.Written with AI assistance and checked against the source at
0f8b44dc0. Worth a human review before acting on it.