Bokeh 3.8.2 安全补丁解析:WebSocket Origin 校验机制与服务器防护配置实践
2026/9/13 12:21:28 网站建设 项目流程

Bokeh 3.8.2 安全补丁解析:WebSocket Origin 校验机制与服务器防护配置实践

【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh

本文聚焦 Bokeh 3.8.2 补丁版本的核心变更——修复 Bokeh 服务器 WebSocket 的 "Incomplete Origin Validation"(不完整的 Origin 校验)安全问题,并结合当前仓库源码,深入讲解 Bokeh 服务器 WebSocket 连接的 Origin 校验实现原理、--allow-websocket-originBOKEH_ALLOW_WS_ORIGIN两种放行配置方式,以及白名单匹配规则。读者将掌握 Bokeh 服务器 WebSocket 连接的完整校验链路,并能够为生产环境部署配置正确的跨站访问策略。

版本概览:一次针对 Bokeh 服务器的安全补丁

根据 3.8.2 版本发布说明,Bokeh 3.8.2 发布于 2026 年 1 月,属于补丁版本(patch release),其唯一变更点如下:

Addressed a security issue with Incomplete Origin Validation for WebSockets in Bokeh server applications

即:修复了 Bokeh 服务器应用中 WebSocket 的不完整 Origin 校验(Incomplete Origin Validation)安全漏洞。该问题位于服务器侧的 WebSocket 握手阶段——当浏览器或其他客户端发起 WebSocket 连接时,如果服务器未严格验证Origin请求头,攻击者可能利用跨站 WebSocket 连接(Cross-Site WebSocket Hijacking,CSWSH)窃取会话或执行越权操作。

这一修复发生在 WebSocket 握手校验的关键路径上,具体实现位于服务器端的 WSHandler 中。下面我们结合当前仓库(即修复后的代码状态)逐一拆解其机制。

Origin 校验的核心实现:WSHandler.check_origin

Bokeh 服务器基于 Tornado 构建,WebSocket 连接由 WSHandler 处理。该类继承自tornado.websocket.WebSocketHandler,并通过重写check_origin()方法(ws.py 第 99-128 行)对每个入站 WebSocket 连接的来源进行校验:

def check_origin(self, origin: str) -> bool: ''' Implement a check_origin policy for Tornado to call. The supplied origin will be compared to the Bokeh server allowlist. If the origin is not allow, an error will be logged and ``False`` will be returned. ''' from ..util import check_allowlist parsed_origin = urlparse(origin) origin_host = parsed_origin.netloc.lower() allowed_hosts = self.application.websocket_origins if settings.allowed_ws_origin(): allowed_hosts = set(settings.allowed_ws_origin()) if check_allowlist(origin_host, list(allowed_hosts)): return True log.error("Refusing websocket connection from Origin '%s'; \ use --allow-websocket-origin=%s or set BOKEH_ALLOW_WS_ORIGIN=%s to permit this; currently we allow origins %r", origin, origin_host, origin_host, allowed_hosts) return False

该校验逻辑的要点:

  • 来源解析:通过urlparse(origin)提取Origin头中的netloc(主机名加端口部分)并转为小写,作为待校验的origin_host
  • 双重来源:允许的来源集合取自两处——由BokehTornado应用层维护的websocket_origins(tornado.py 第 557-561 行),以及全局设置中的BOKEH_ALLOW_WS_ORIGIN环境变量(settings.allowed_ws_origin())。当环境变量非空时,环境变量配置优先;
  • 拒绝即断连:一旦校验不通过,立即记录 error 级日志并返回False,Tornado 将拒绝本次 WebSocket 握手,连接被终止。日志会明确提示使用者通过--allow-websocket-originBOKEH_ALLOW_WS_ORIGIN放行指定来源,便于运维排障。

从实现顺序看,check_origin是 WebSocket 握手的第一个安全关口——只有通过 Origin 校验的连接,才会进入后续的 token 签名校验(check_token_signature)与 session 创建流程(ws.py 第 130-167 行)。因此,本次补丁所修复的 "Incomplete Origin Validation" 正是这一最外层防线。

白名单匹配引擎:check_allowlist 与 match_host

check_origin调用的check_allowlist定义在 src/bokeh/server/util.py 中,它负责把待校验主机与白名单模式逐条比对:

def check_allowlist(host: str, allowlist: Sequence[str]) -> bool: if ':' not in host: host = host + ':80' if host in allowlist: return True return any(match_host(host, pattern) for pattern in allowlist)

匹配规则由match_host(util.py 第 157-246 行)具体实现,从源码与文档字符串中可归纳出以下判定规则:

场景示例结果
完全相等(含端口)192.168.0.1:80vs192.168.0.1:80匹配
未指定端口视为:80192.168.0.1:80vs192.168.0.1匹配
端口不同192.168.0.1:80vs192.168.0.1:8080不匹配
通配符*(匹配任意主机、任意端口)alicevs*匹配
通配符按点分片段匹配192.168.0.1vs192.168.*.*匹配
片段数必须一致(防子域误匹配)example.com.bad.comvsexample.com不匹配
通配符端口alice:8080vs*:80不匹配

值得注意的细节:

  • 默认拒绝跨站match_host要求主机片段数完全一致,例如example.com.bad.com不会被example.com模式匹配,从机制上杜绝了子域名前缀绕过;
  • 通配符警告create_hosts_allowlist(util.py 第 94-155 行)在处理含*的主机时会输出警告日志,提示通配符将允许来自多个(甚至全部)主机名的连接,建议仅在不关心来源限制的场景使用;
  • 默认放行本机:当未配置任何--allow-websocket-origin时,create_hosts_allowlist返回['localhost:<port>'],即默认仅允许来自本机地址的连接——这正是 "默认禁止跨站" 安全基线的落地实现。

配置放行来源:命令行参数与环境变量

Bokeh 提供两种方式为 WebSocket 连接放行额外的 Origin,二者在运行时都会汇入上述校验链。

方式一:--allow-websocket-origin 命令行参数

bokeh serve子命令支持--allow-websocket-origin参数,定义于 src/bokeh/command/subcommands/serve.py 第 573-579 行,元变量为HOST[:PORT],可重复指定:

bokeh serve app_script.py --allow-websocket-origin foo.com:8081 bokeh serve app_script.py \ --allow-websocket-origin foo.com:8081 \ --allow-websocket-origin bar.com:8081

命令行帮助信息(serve.py 第 175-186 行)明确指出:

By default, cross site connections to the Bokeh server websocket are not allowed. You can enable websocket connections originating from additional hosts by specifying them with theBOKEH_ALLOW_WS_ORIGINenvironment variable or the--allow-websocket-originoption.

在服务器启动时,该参数值经由 src/bokeh/server/server.py 第 490-502 行 的处理:若指定了 unix socket,则create_hosts_allowlist(opts.allow_websocket_origin, None)(端口留空);常规 TCP 监听下则传入实际端口self.port,最终以extra_websocket_origins参数注入BokehTornado,成为 tornado.py 第 398-405 行 中self._websocket_origins的初始集合。

方式二:BOKEH_ALLOW_WS_ORIGIN 环境变量

全局设置 src/bokeh/settings.py 第 620-622 行 定义了同名设置项:

allowed_ws_origin = PrioritizedSetting[list[str]]( "allowed_ws_origin", "BOKEH_ALLOW_WS_ORIGIN", default=[], convert=convert_str_seq, help="A comma-separated list of allowed websocket origins for Bokeh server applications." )

使用方式为设置逗号分隔的主机列表:

export BOKEH_ALLOW_WS_ORIGIN="foo.com:8081,bar.com:8081" bokeh serve app_script.py

从前述check_origin的实现可见:环境变量设置优先于命令行参数——当settings.allowed_ws_origin()返回非空集合时,会直接覆盖websocket_origins(即命令行来源)作为唯一判定依据。因此若两种方式同时配置,请确保它们语义一致,避免误放行或误拦截。

修复后的安全边界与最佳实践

结合 3.8.2 补丁修复的目标与当前源码的完整校验链路,可以归纳出生产部署时的安全建议:

  1. 默认保持拒绝跨站:不要为图省事配置--allow-websocket-origin=*或全通配白名单。create_hosts_allowlist会就通配符输出警告日志,且match_host*匹配任意主机与端口,属于高风险配置,仅适用于纯本地或完全无敏感数据的场景;
  2. 精确列出前端域名与端口:当 Bokeh 应用被嵌入其他站点页面时,应把承载页面的确切host[:port]逐条加入白名单,端口必须与实际访问端口一致(默认 80 端口可省略);
  3. 多层防护协同:Origin 校验只是第一道防线。部署在公网时还应配合 serve.py 中说明 的注意点——--use-xheaders不应直接暴露给公网;建议让 Bokeh 服务器位于反向代理(如 Nginx)之后,由代理层做 SSL 终止与请求头清洗,再配合--session-ids signed(签名会话 ID)与BOKEH_SECRET_KEY保护会话身份(见 serve.py 第 228-274 行);
  4. 关注错误日志:当浏览器控制台出现 WebSocket 连接失败时,服务器端会输出形如Refusing websocket connection from Origin '...'的 error 日志,其中包含了被拒的 Origin 与当前允许列表,这是排查放行配置最直接的依据;
  5. 及时升级:包含安全修复的 3.8.2 属于补丁版本,建议所有使用 3.8.x 系列部署 Bokeh 服务器(bokeh serve)的团队尽快升级,以消除 Incomplete Origin Validation 带来的跨站 WebSocket 风险。

小结

Bokeh 3.8.2 以一次精准的补丁修复了 Bokeh 服务器 WebSocket 的 Origin 校验缺陷,其修复落实在WSHandler.check_origincheck_allowlist/match_host的完整链路中:默认仅放行本机来源、拒绝跨站连接、支持命令行与环境变量两种精细化的白名单配置。理解这条校验链与匹配规则,是安全部署 Bokeh 服务器、正确配置--allow-websocket-originBOKEH_ALLOW_WS_ORIGIN的前提,也是本次安全补丁真正发挥防护作用的关键。

【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询