EEF-CVE-2026-110314

Source
https://cna.erlef.org/osv/EEF-CVE-2026-110314.html
Import Source
https://cna.erlef.org/osv/EEF-CVE-2026-110314.json
JSON Data
https://api.osv.dev/v1/vulns/EEF-CVE-2026-110314
Aliases
  • CVE-2026-110314
  • GHSA-2v5v-8f9v-xh85
Published
2026-10-26T13:31:18Z
Modified
2026-10-26T13:56:06Z
Severity
  • 6.3 (Medium) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N CVSS Calculator
Summary
WebSocket frames keep reaching the WebSock after a server-initiated close in Bandit
Details

Summary

Client-Side Enforcement of Server-Side Security vulnerability in the WebSocket connection handling of mtrudel bandit allows a remote client to keep running WebSock handler code after the server has stopped its connection, via data frames sent after ignoring the server's Close frame.

When a WebSock callback returns {:stop, ...}, Bandit.WebSocket.Connection calls terminate/2, sends Close and shuts down the write side, but keeps the connection process running in a :closing state. handle_frame/3 and handle_info/3 never check that state, so later frames still reach handle_in/2 and later messages reach handle_info/2, with the state from the stop tuple, until the client sends Close, TCP drops or the idle timeout fires. A client refused in init/1 after a failed token check could still run an admin-only action.

This issue affects bandit: from 0.5.1 before 1.14.0.

Details

1. Stop without close. In Bandit.WebSocket.Connection, do_stop/4 calls terminate/2, sends the Close frame and runs shutdown(:write). It then returns {:continue, %{connection | state: :closing}}, so Bandit.WebSocket.Handler keeps the process alive.

2. No state check. handle_frame/3 and handle_info/3 never check connection.state. Every later data frame still reaches handle_in/2, and every later message still reaches handle_info/2, with the state from the stop tuple.

3. Client-controlled lifetime. The connection ends only when the client sends Close, TCP drops, or the idle timeout fires, and each client frame resets that timeout. All stops through do_stop are affected: {:stop, :normal, ...}, {:stop, {:shutdown, :disconnected}, ...} and {:stop, {:shutdown, :restart}, ...}, which is what Phoenix's :socket_drain returns. A banned user who was kicked kept posting for longer than the idle timeout.

Proof of concept

  1. Serve a WebSock whose init/1 returns {:stop, :normal, {4401, "unauthorized"}, state} for a wrong token, and whose handle_in/2 runs an admin-only delete_all_users action when user_id is admin.
  2. Upgrade with ?user_id=admin&token=wrong. The server calls terminate/2 and sends a Close frame with code 4401.
  3. Ignore the Close frame and send a masked text frame delete_all_users.
  4. handle_in/2 runs delete_all_users as admin.

Impact

A remote client that ignores the Close frame can keep invoking a WebSock application's handlers after the application refused or ended its session, bypassing an authorization check in init/1 or a kick or ban. This affects WebSock applications that rely on {:stop, ...} to end a session.

Workarounds

Mark the WebSock state as stopped whenever a callback returns {:stop, ...}, and have handle_in/2 and handle_info/2 return {:ok, state} without acting while that mark is set.

Database specific
{
    "capec_ids":  [
        "CAPEC-202"
    ],
    "cpe_ids":  [
        "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*"
    ],
    "cwe_ids":  [
        "CWE-602"
    ]
}
References
Credits
    • Peter Ullrich - REPORTER
    • Mat Trudel - REMEDIATION_DEVELOPER
    • Jonatan Männchen / EEF - ANALYST

Affected packages

Hex / bandit

Package

Name
bandit
Purl
pkg:hex/bandit

Affected ranges

Type
SEMVER
Events
Introduced
0.5.1
Fixed
1.14.0

Affected versions

0.*
0.5.1
0.5.2
0.5.3
0.5.4
0.5.5
0.5.6
0.5.7
0.5.8
0.5.9
0.5.10
0.5.11
0.6.0
0.6.1
0.6.2
0.6.3
0.6.4
0.6.5
0.6.6
0.6.7
0.6.8
0.6.9
0.6.10
0.6.11
0.7.0
0.7.1
0.7.2
0.7.3
0.7.4
0.7.5
0.7.6
0.7.7
1.*
1.0.0-pre.1
1.0.0-pre.2
1.0.0-pre.3
1.0.0-pre.4
1.0.0-pre.5
1.0.0-pre.6
1.0.0-pre.7
1.0.0-pre.8
1.0.0-pre.9
1.0.0-pre.10
1.0.0-pre.11
1.0.0-pre.12
1.0.0-pre.13
1.0.0-pre.14
1.0.0-pre.15
1.0.0-pre.16
1.0.0-pre.17
1.0.0-pre.18
1.0.0
1.1.0
1.1.1
1.1.2
1.1.3
1.2.0
1.2.1
1.2.2
1.2.3
1.3.0
1.4.0
1.4.1
1.4.2
1.5.0
1.5.1
1.5.2
1.5.3
1.5.4
1.5.5
1.5.6
1.5.7
1.6.0
1.6.1
1.6.2
1.6.3
1.6.4
1.6.5
1.6.6
1.6.7
1.6.8
1.6.9
1.6.10
1.6.11
1.7.0
1.8.0
1.9.0
1.10.0
1.10.1
1.10.2
1.10.3
1.10.4
1.11.0
1.11.1
1.12.0
1.12.1
1.12.2
1.12.3
1.12.4
1.12.5
1.13.0
1.13.1

Database specific

source
"https://cna.erlef.org/osv/EEF-CVE-2026-110314.json"

Git / github.com/mtrudel/bandit

Affected ranges

Type
GIT
Repo
https://github.com/mtrudel/bandit
Events

Database specific

source
"https://cna.erlef.org/osv/EEF-CVE-2026-110314.json"