WEBGL_debug_renderer_info:隐私与 renderer 边界
从扩展查询到 getParameter 追踪可选的 WebGL renderer 暴露,不把 renderer 字符串当作设备身份。
BotBrowser Team
WEBGL_debug_renderer_info 是可选的诊断扩展。它可以通过 getParameter() 暴露 vendor 和 renderer 字符串,但不是身份 API。真正需要区分的是哪个操作执行了、哪个操作返回 null,以及应用实际需要什么。
BotBrowser 文档介绍基于 profile 的 WebGL 控制。该文档不会把扩展缺失变成某个设置的证据,返回 renderer 也不能证明物理 GPU 或用户身份。阅读反爬或隐私信号时,这个边界必须保留。
TL;DR
getExtension('WEBGL_debug_renderer_info')与创建 WebGL context 是两个步骤。- 扩展定义
UNMASKED_VENDOR_WEBGL和UNMASKED_RENDERER_WEBGL;返回值是观察结果,不是身份。 null、异常、序列化后的空字段和返回字符串代表不同状态。- 缺失值不能证明隐私偏好、浏览器家族或自动化结论。
- 先记录采集阶段和任务结果,再决定是否保存原始 renderer。
Contents
流程把 API 观察结果与隐私、身份解释分开。
扩展本身是可选的
Khronos 规范 定义额外诊断常量,但不替代 context 创建。应用可以得到可用的 WebGLRenderingContext,却没有扩展对象;如果 context 创建失败,扩展查询根本没有发生。
MDN 提到浏览器隐私策略可能影响暴露。这是有文档依据的例子,不是所有缺失值的通用原因。没有独立策略证据时,应保留观察到的分支并把原因留为未知。
页面如果按设计不请求该字段,只能记录 not_requested,不能写成 extension_unavailable。
查询与参数调用是不同证据
getExtension() 在当前 context 不提供该名称时返回对象或 null。它回答的是可选接口是否在这一时刻暴露。
getParameter() 需要扩展对象,并通过扩展常量读取参数。异常、无效常量或序列化器删除字段,都应进入独立错误字段。把所有情况写成空字符串会丢掉排障证据。
| 状态 | 最小观察 | 不能说明 |
|---|---|---|
not_requested | 没有执行扩展查询 | context 或扩展是否可用 |
context_unavailable | getContext() 没有得到可用 context | 创建失败的原因 |
extension_unavailable | 活跃 context 返回 null | 哪个策略造成缺失 |
parameter_missing | 参数缺失或被拒绝 | 某个隐私设置 |
reported | 参数值已返回并记录 | 物理设备、用户或 bot 身份 |
这些是应用记录标签,不是额外的 WebGL 返回值。它们让复核者能追问具体执行了哪个调用。
renderer 字符串的含义很窄
这个字符串只是一个 context 中一层 API 的观察值。共享软件层和虚拟化环境可能返回相同名称,所以它不能证明特定物理 GPU、用户或检测器结论。返回值存在也不能证明所有隐私保护都关闭,缺失也不能证明某项保护开启。
WebGL 总体分析讨论多信号组合;缺失值分析讨论 context 生命周期。做受控比较时固定 canvas、context 类型、版本和采集阶段,只改变一个条件;除非事故确实需要,否则对原始字符串脱敏。
一份脱敏的对比记录
下面是应用记录模板,不是 BotBrowser 的运行结果:
{
"applicationRelease": "support-ui-14",
"context": "webgl2",
"extensionLookup": "reported",
"parameters": { "UNMASKED_VENDOR_WEBGL": "redacted", "UNMASKED_RENDERER_WEBGL": "redacted" },
"taskOutcome": "visualization-complete",
"collectionPhase": "after-context-create",
"rawValueRetention": "not-retained"
}
记录保留分支和用户可见的任务结果。查询为 null 时只改变状态,不改写任务结果;context 失败属于更早阶段。单个 renderer 字符串无法揭示反爬检测器的决定。
两个常量,两项观察
规范给出了常量名称,但没有规定分析数据结构。每次读取应单独记录;如果只有一个调用成功,不要推造第二个值。WebGL 1 与 WebGL 2 也应分开比较。getContext('webgl2') 成功并不能证明 getContext('webgl') 会返回相同 context 或暴露相同扩展。MDN 的 getContext 参考说明了 context 模式冲突;这是 API 调用的前置条件,与扩展策略是不同问题。
表格可以逐项保留调用边界:
| Context 请求 | Context 结果 | 扩展查询 | 参数结果 | 安全解释 |
|---|---|---|---|---|
webgl | object | object | 两个字符串 | 此阶段返回了可选元数据 |
webgl | object | null | 未执行 | 扩展不可用;原因尚未确定 |
webgl2 | null | 未执行 | 未执行 | 扩展证据产生前 context 创建失败 |
webgl2 | object | object | 一个异常 | 参数收集失败;不能据此判定扩展缺失 |
webgl | object | object | 序列化字段为空 | 检查序列化;API 返回值未知 |
最后一行在生产环境尤其容易误读:JSON 可能省略 undefined,脱敏层可能将值替换为 "",界面也可能显示占位符。应在这些转换前保存状态。采集阶段也会改变比较含义。MDN 的 webglcontextlost 事件文档描述生命周期中断,isContextLost()用于检查该状态;二者都不能说明扩展永久不可用。可以用 after-context-create、after-context-restore 和 fallback-render 标注应用阶段。不要把 context 丢失前的值与丢失期间的缺失值当成稳定浏览器属性比较。恢复后资源可能需要重新创建,缓存的 renderer 字符串也可能属于较早阶段。
脱敏与可复核记录
支持排障通常只需知道是否查询了扩展、每个常量是否返回字符串,以及图表或备用流程是否完成。下面这些字段保留所需事实,又不形成长期硬件标识:
| 字段 | 示例 | 保留理由 |
|---|---|---|
contextRequest | webgl2 | 还原请求的 API 边界 |
extensionState | reported | 区分扩展查询与 context 创建 |
vendorShape | string | 确认类型而不保留具体值 |
rendererShape | string | 确认第二个调用的返回类型 |
taskOutcome | fallback-visible | 区分用户影响与诊断结果 |
phase | after-context-create | 避免混合生命周期阶段 |
retention | redacted-after-validation | 让隐私保留决定可审计 |
Khronos 规范定义名称和参数约定,MDN 说明方法行为;这些来源都不能证明某个网站如何将 renderer 与画布像素、字体或网络信号组合。修改应用的信号收集逻辑之前,先写出每一步的预期分支,再检查可重复的输入和输出:
| 检查项 | 保持不变的输入 | 可观察输出 | 解释边界 |
|---|---|---|---|
| Context 请求 | Canvas 元素与请求名称 | object 或 null | 只说明创建是否就绪 |
| 扩展查询 | 相同 context 与精确名称 | object 或 null | 只说明可选接口是否可用 |
| Vendor 参数 | 相同扩展对象 | 字符串、异常或缺失字段 | 只说明一个诊断值 |
| Renderer 参数 | 相同扩展对象 | 字符串、异常或缺失字段 | 只说明另一个诊断值 |
| 序列化 | 相同内存记录 | 保留、脱敏或省略键 | 只说明应用转换 |
| 用户任务 | 相同图表或备用流程 | 完成、备用或中断 | 产品结果,不是身份 |
如果第二项返回 null,第三、四项就没有执行;记为“空”会伪造测量。比较普通浏览器与自动化环境时,固定 context 请求、扩展名称和采集阶段。声明的配置可以与观察到的分支对照,但分支本身无法认证配置。
BotBrowser 的范围与限制
BotBrowser WebGL 文档 是 profile 控制的产品来源。Khronos 与 MDN 说明 Web API,不说明 BotBrowser profile 行为。授权比较可以验证应用是否稳定记录分支,但不能保证第三方标签或每个主机都有相同结果。
FAQ
null 是否意味着 WebGL 被禁用?
不是。它只涉及一个可选扩展;context 创建是另一项检查。
renderer 字符串能识别 GPU 吗?
不能。它是可能共享、虚拟化或被隐藏的 API 值。
常规分析是否应该保存原始字符串?
不应默认保存。保留状态、阶段和任务结果;原始值必须有明确的支持目的和有限保留期。
Sources
- Khronos: WEBGL_debug_renderer_info
- MDN: WEBGL_debug_renderer_info
- MDN: getExtension()
- MDN: getParameter()
- BotBrowser: WebGL
Practical conclusion
把 WEBGL_debug_renderer_info 当作可选观察路径。分别记录 context 创建、扩展查询、参数读取和任务结果。缺失值需要自己的证据,返回值也只能窄解释,不能变成身份结论。
本文属于指南: 什么是浏览器指纹?原理、风险、信号与隐私边界