
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-origin与BOKEH_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 HijackingCSWSH窃取会话或执行越权操作。这一修复发生在 WebSocket 握手校验的关键路径上具体实现位于服务器端的 WSHandler 中。下面我们结合当前仓库即修复后的代码状态逐一拆解其机制。Origin 校验的核心实现WSHandler.check_originBokeh 服务器基于 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_originstornado.py 第 557-561 行以及全局设置中的BOKEH_ALLOW_WS_ORIGIN环境变量settings.allowed_ws_origin()。当环境变量非空时环境变量配置优先拒绝即断连一旦校验不通过立即记录 error 级日志并返回FalseTornado 将拒绝本次 WebSocket 握手连接被终止。日志会明确提示使用者通过--allow-websocket-origin或BOKEH_ALLOW_WS_ORIGIN放行指定来源便于运维排障。从实现顺序看check_origin是 WebSocket 握手的第一个安全关口——只有通过 Origin 校验的连接才会进入后续的 token 签名校验check_token_signature与 session 创建流程ws.py 第 130-167 行。因此本次补丁所修复的 Incomplete Origin Validation 正是这一最外层防线。白名单匹配引擎check_allowlist 与 match_hostcheck_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_hostutil.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_allowlistutil.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[], convertconvert_str_seq, helpA comma-separated list of allowed websocket origins for Bokeh server applications. )使用方式为设置逗号分隔的主机列表export BOKEH_ALLOW_WS_ORIGINfoo.com:8081,bar.com:8081 bokeh serve app_script.py从前述check_origin的实现可见环境变量设置优先于命令行参数——当settings.allowed_ws_origin()返回非空集合时会直接覆盖websocket_origins即命令行来源作为唯一判定依据。因此若两种方式同时配置请确保它们语义一致避免误放行或误拦截。修复后的安全边界与最佳实践结合 3.8.2 补丁修复的目标与当前源码的完整校验链路可以归纳出生产部署时的安全建议默认保持拒绝跨站不要为图省事配置--allow-websocket-origin*或全通配白名单。create_hosts_allowlist会就通配符输出警告日志且match_host中*匹配任意主机与端口属于高风险配置仅适用于纯本地或完全无敏感数据的场景精确列出前端域名与端口当 Bokeh 应用被嵌入其他站点页面时应把承载页面的确切host[:port]逐条加入白名单端口必须与实际访问端口一致默认 80 端口可省略多层防护协同Origin 校验只是第一道防线。部署在公网时还应配合 serve.py 中说明 的注意点——--use-xheaders不应直接暴露给公网建议让 Bokeh 服务器位于反向代理如 Nginx之后由代理层做 SSL 终止与请求头清洗再配合--session-ids signed签名会话 ID与BOKEH_SECRET_KEY保护会话身份见 serve.py 第 228-274 行关注错误日志当浏览器控制台出现 WebSocket 连接失败时服务器端会输出形如Refusing websocket connection from Origin ...的 error 日志其中包含了被拒的 Origin 与当前允许列表这是排查放行配置最直接的依据及时升级包含安全修复的 3.8.2 属于补丁版本建议所有使用 3.8.x 系列部署 Bokeh 服务器bokeh serve的团队尽快升级以消除 Incomplete Origin Validation 带来的跨站 WebSocket 风险。小结Bokeh 3.8.2 以一次精准的补丁修复了 Bokeh 服务器 WebSocket 的 Origin 校验缺陷其修复落实在WSHandler.check_origin→check_allowlist/match_host的完整链路中默认仅放行本机来源、拒绝跨站连接、支持命令行与环境变量两种精细化的白名单配置。理解这条校验链与匹配规则是安全部署 Bokeh 服务器、正确配置--allow-websocket-origin与BOKEH_ALLOW_WS_ORIGIN的前提也是本次安全补丁真正发挥防护作用的关键。【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考