VYPR
Moderate severityOSV Advisory· Published Jan 8, 2026· Updated Jan 23, 2026

Bokeh server applications have Incomplete Origin Validation in WebSockets

CVE-2026-21883

Description

Bokeh is an interactive visualization library written in Python. In versions 3.8.1 and below, if a server is configured with an allowlist (e.g., dashboard.corp), an attacker can register a domain like dashboard.corp.attacker.com (or use a subdomain if applicable) and lure a victim to visit it. The malicious site can then initiate a WebSocket connection to the vulnerable Bokeh server. Since the Origin header (e.g., http://dashboard.corp.attacker.com/) matches the allowlist according to the flawed logic, the connection is accepted. Once connected, the attacker can interact with the Bokeh server on behalf of the victim, potentially accessing sensitive data, or modifying visualizations. This issue is fixed in version 3.8.2.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
bokehPyPI
< 3.8.23.8.2

Affected products

1

Patches

1
cedd113b0e27

handle wildcard host with port correctly

https://github.com/bokeh/bokehBryan Van de VenJan 5, 2026via ghsa
3 files changed · +12 2
  • src/bokeh/server/util.py+5 0 modified
    @@ -217,6 +217,7 @@ def match_host(host: str, pattern: str) -> bool:
             False
     
         '''
    +    # This is for a wildcard match without any port restriction
         if pattern == "*":
             return True
     
    @@ -233,6 +234,10 @@ def match_host(host: str, pattern: str) -> bool:
         if pattern_port is not None and host_port != pattern_port:
             return False
     
    +    # This is for a wildcard match including any port restriction
    +    if pattern == "*":
    +        return True
    +
         host_parts = host.split('.')
         pattern_parts = pattern.split('.')
     
    
  • tests/unit/bokeh/server/test_util.py+2 0 modified
    @@ -129,6 +129,8 @@ def test_match_host() -> None:
             assert util.match_host('alice:80', '*') is True
             assert util.match_host('alice:80', '*:80') is True
             assert util.match_host('alice:8080', '*:80') is False
    +        assert util.match_host("192.168.0.1:80", '*:80') is True
    +        assert util.match_host("192.168.0.1:8080", '*:80') is False
     
     #-----------------------------------------------------------------------------
     # Dev API
    
  • tests/unit/bokeh/server/views/test_ws.py+5 2 modified
    @@ -76,6 +76,7 @@ def test_uses_auth_request_handler() -> None:
         pytest.param(["*"],                "http://example.com",      id="global wildcard"),
         pytest.param(["example.*"],        "http://example.com",      id="partial wildcard"),
         pytest.param(["example.com:*"],    "http://example.com",      id="port wildcard"),
    +    pytest.param(["*:81"],             "http://example.com:81",   id="host wildcard"),
         pytest.param(["example.com:80"],   "http://example.com",      id="implicit port 80"),
         pytest.param(["example.com:8080"], "http://example.com:8080", id="explicit port"),
         pytest.param(["example.com"],      "http://example.com",      id="exact match"),
    @@ -97,9 +98,11 @@ async def test_ws_handler_accepts_allowed_origins(
     
     BAD_ORIGIN_CASES = (
         pytest.param(["example.com"],    "http://example.com.bad.com", id="subdomain rejection"),
    -    pytest.param(["example.com"],    "http://foo.com",             id="exact name mismatch"),
    +    pytest.param(["example.com"],    "http://foo.com",             id="exact host mismatch"),
    +    pytest.param(["example.com:80"], "http://foo.com:80",          id="exact host mismatch with port"),
         pytest.param(["example.com.*"],  "http://example.com",         id="pattern mismatch"),
    -    pytest.param(["example.com:80"], "http://example.com:8080",    id="port mismatch"),
    +    pytest.param(["example.com:80"], "http://example.com:8080",    id="port mismatch with exact host"),
    +    pytest.param(["*:81"],           "http://example.com:8080",    id="port mismatch with wildcard host"),
     )
     
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.