CVE-2026-39807 - Bandit trusts client-supplied URI scheme on plaintext connections

📡 GitHub-Advisory · 2026-05-07

CVE-2026-39807 - Bandit trusts client-supplied URI scheme on plaintext connections

CVE-2026-39807

GHSA-375f-4r2h-f99j MEDIUM erlang/bandit

CVE: CVE-2026-39807

Summary

Bandit reflects the client-supplied URI scheme into conn.scheme without verifying the actual transport. Over a plaintext HTTP/1.1 connection (or h2c), an unauthenticated attacker can send an absolute-form request target like GET https://victim/path HTTP/1.1 and the application observes conn.scheme = :https even though no TLS was negotiated. Any downstream Plug logic that trusts conn.scheme as a security signal — Plug.SSL's "already secure, don't redirect" branch, secure: true cookie flagging, audit logging, CSRF/SameSite gating — is silently misled into treating an attacker's plaintext connection as encrypted.

The vulnerability was introduced on Jun 8, 2023: https://github.com/mtrudel/bandit/commit/ff2f829326cd5dcf7335939aef9775269d881e28

Details

The bug is in lib/bandit/pipeline.ex at determine_scheme/2 (around line 89). The function takes the request target's scheme and the transport's secure? flag and produces the URI scheme used to build the %Plug.Conn{}. The third match clause is {_, scheme} -> scheme — i.e. whenever the client supplies *any* scheme on the request target, the function returns that scheme verbatim and discards secure? entirely.

Two attacker-controlled inputs reach this code path:

  • HTTP/1.1 absolute-form request targets (RFC 9112 §3.2.2), e.g. GET https://victim/path HTTP/1.1.
  • HTTP/2 :scheme pseudo-header, which is a free-form string sent by the client.

Neither value is constrained to match the actual transport. On a plaintext TCP listener (or h2c), a client can declare https and Bandit will pass %URI{scheme: "https"} into Plug.Conn.Adapter.conn/5, producing conn.scheme == :https. There is no guard in determine_scheme/2; the discarding of secure? is deliberate.

Suggested fix: when secure? is true, force the scheme to "https"; when false, force it to "http" — or reject the request with 400 Bad Request if the supplied scheme disagrees with the transport's actual securit


📌 来源: GitHub-Advisory | 🆔 CVE-2026-39807 | 📅 2026-05-07

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)