你修一个 WebView 漏洞,方式和修别的漏洞一样——除了你其实修不了。渲染你应用内结账、登录、表单的浏览器引擎是 Chromium,而在 Android 上,这个引擎住在一个由 Google 和 Play 商店更新、而不是你团队更新的系统组件里。你某些最敏感屏幕的安全,由一个你既控制不了、也钉不住版本的自带软件决定。

你并不拥有的引擎

从 Android 5.0 起,Google 把 WebView 从操作系统里剥离,改由 Play 商店作为可更新应用分发。在 Android 7.0 及以后,只要装了 Chrome,系统往往直接用 Chrome 充当 WebView 提供方。实际后果很直白:你 WebView 背后渲染引擎的版本,是用户设备「恰好有」的那个,按 Google 的节奏更新,而不是你的。你的签名二进制可以带着修好的原生库;WebView 引擎却是别人在别人时钟上的二进制。

碎片化是常态,不是例外

「大家都在较新的 Chromium 上」是一个安慰性的幻觉。设备厂商定制 WebView、系统更新滞后、部分厂商还限制切回 Google WebView。在没有 Google 移动服务——亚洲市场相当大一块——的设备上,Play 商店更新根本够不到 WebView。公开分布数据显示,Chromium 110 及以上的 WebView 在 2024 年第二季度覆盖约 89% 的 Android 设备,也就是说仍有两位数百分比跑着更老的支线,其中一些落后二十个以上版本。华为的 WebView 上限约 Chromium 114,较老的荣耀设备停在 116 附近。你那「一份 H5」,跑在一个你永远测不全的引擎矩阵上。

共享组件一坏,大家全坏

这种依赖是双向的。2021 年 3 月,一次经 Play 商店推送的有缺陷 WebView 更新,导致几十款依赖它的应用启动即崩溃——Gmail、Google Pay、Samsung Pay 以及众多银行 App 在全球数百万用户手上直接不可用。修复要靠 Google 撤回坏版本并推出补丁版,而受影响的用户只能等。你 App 的稳定性,成了你没写、也没选日子的那个组件的 hostage。

你的安全补丁,在等别人的队列

假设你发现某类基于 WebView 的攻击正在针对你的用户。你能发什么?在引擎层面基本什么也发不了。你能加固自己的代码,但底层的 Chromium 补丁只有 Google 发布、且用户真的更新了组件才会到达——还要经过设备、地区、运营商、是否开启自动更新的层层关卡。Google 自己的安全公告把 WebView 相关 CVE 列为反复出现的高危类别(某 2023 年公告中约占高危漏洞的 17%)。补丁存在;它到达用户手机的时间,不由你指挥。

runtime 的解法

宿主自有 runtime 用平台原生 UI 工具包渲染小程序,而不是借来的浏览器引擎。没有第二个 Chromium 需要你在上千种设备画像里追踪版本。你的业务逻辑装在你控制、已签名的版本化包里,于是安全修复随你的发布节奏走——不是 Google 的,不是运营商的。你不再等别人的更新队列,也不用再猜哪个用户正跑着你从没测过的引擎支线。

维度WebView宿主自有 runtime
引擎版本控制由 Android / Play 商店 / 设备厂商决定由你决定,写进签名包
安全补丁到达受 Google 发布 + 用户更新双重卡控随你的发布一起到达
设备碎片化野外存在几十条 Chromium 支线一个你构建和测试的 runtime
共享组件故障一次坏更新可让多款 App 同时崩仅隔离在你自己的 App
你能钉住的引擎层面什么也钉不住整个 runtime 版本

这个模式在整系列里反复出现:关键路径一旦离开你的签名二进制、变成「从你服务器拉来的文档」,控制权也一并离开。用 WebView,你连「哪个引擎在渲染它」都保证不了。runtime 把这份保证交还给你。

参考来源