WebView 的默认导航策略两个方向都错。放任不管,每个链接——包括银行的支付页、还有钓鱼仿冒页——都在你自己的 WebView 里打开,把你的 Referer、会话 Cookie,以及真实披露过的 CVE 里写在 URL 上的鉴权令牌一并泄露。动手改又会在用户第一次点手机号时抛出 ERR_UNKNOWN_URL_SCHEME 崩溃。而默认没有宿主白名单,一次未设防的桥接调用就成了静默账号接管。宿主自有 runtime 按链接、按来源决定什么该出去、什么该留下。
默认就是「什么都在这里面打开」
默认情况下,WebView 会把每个 https 目标都在内部加载。点一下合作方的商城页、银行跳转页,甚至一篇外部新闻,都在你 App 自己的外壳里渲染。方便,直到它变成负债:目标站点现在能拿到你的 Referer 响应头、你拼在 URL 上的任何令牌,以及你的 WebView 写在 User-Agent 里的那个稳定用户 ID。2026 年 Mira Android 应用就被披露了这件事(CVE-2026-66832,CVSS 6.5)——它把用户实时的会话令牌作为查询参数拼进目标 URL,把一个稳定的用户 ID 塞进 WebView 的 User-Agent,两者都被传给第三方站点、Referer 日志,以及 WebView 内执行的任何脚本。这是账号接管,不是纸面假设。
改得不好,就崩溃
常见的反应是重写 shouldOverrideUrlLoading,把非 http 的 scheme 转交给系统。返回值写反了,啥也不发生;漏掉 tel:、mailto:、sms:、geo: 或 intent://,用户就看到 ERR_UNKNOWN_URL_SCHEME——WebView 根本渲染不了它不认识的 scheme。Android 7+(API 24)强制要求新方法签名,返回值写错就抛 ActivityNotFoundException 直接崩。Android 11+ 又加了包可见性规则,跳转到另一个 App 的深链若未声明就会静默失败。修复是真的,但琐碎,而且它活在 Web 团队并不拥有的原生代码里。
没有白名单,桥就是敞开的大门
更深的失败是结构性的。导航策略与 JS 桥,是 Web 内容与原生能力之间的两道闸门;而在一份公开审计里(SilentGrid),两道都不在:桥把实时鉴权令牌回给页面上任意 JavaScript,WKWebView 的 decidePolicyFor 又对任何 https 来源放行、毫无主机校验。一个精心构造的深链就足以加载攻击页、调用令牌处理器、把会话窃走——一次点击,受害者毫无察觉。反向 Tabnabbing 又添一把火:没有 rel="noopener" 打开的页面能悄悄把你的 opener 重定向到钓鱼仿冒页,而 WebView 并不套用浏览器的那层保护默认。
runtime 解法
宿主自有 runtime 把导航边界变成显式且被强制执行的规则。它维护一份宿主白名单:第一方域名在 runtime 内加载,已知的 App scheme(tel:、mailto:、market:)转交系统并带安全兜底,其余一律要么外部浏览器打开、要么拦截。JS 桥按来源校验、最小权限,所以一个来自不可信 catalog 条目的页面够不到凭据处理器。该出去的链接,出去;该留下的令牌,留下。
| 维度 | WebView | 宿主自有 runtime |
|---|---|---|
| 默认行为 | 每个 https 都在 WebView 内打开 | 第一方在内,其余出去或拦截 |
| 外部链接 | Referer、URL 令牌、UA ID 泄露给第三方 | 宿主白名单管控每个来源 |
| 自定义 scheme | 未处理即 ERR_UNKNOWN_URL_SCHEME 崩溃 | 转交系统并带安全兜底 |
| JS 桥 | 常无来源校验 | 按来源校验、最小权限 |
| 反向 Tabnabbing | 不强制 noopener | 每个新窗口强制开启 |
本系列的主线始终是「控制权」。WebView 把一条两个方向都不安全的默认导航边界、一个谁调用都信任的桥,塞给你。runtime 把边界变成一条由你书写的策略——按链接、按来源、按 catalog 条目。对一套承载别人页面在你的 App 里交易的 catalog 来说,这就是「受控店门」与「敞开大门」的差距。
参考来源
- CVE-2026-66832——Mira Android 将实时会话令牌写在 URL 查询里、稳定 ID 写在 WebView UA 中,泄露给第三方(CVSS 6.5) — 2026 披露:鉴权材料与追踪标识在 App 内 WebView 流程中越出应用边界。
- 通过 WebView 桥窃取鉴权令牌——无来源校验的 JS 桥 + 无主机白名单的导航策略链式导致静默账号接管 — SilentGrid 审计:一次构造深链、一次点击、令牌被窃。
- Android WebView 与 App Links:默认行为把一切都加载在内部 — App Links、tel:、mailto:、intent:// 全被 WebView 困住,除非拦截。
- ERR_UNKNOWN_URL_SCHEME:WebView 只渲染 http/https/file/data/about,其余 scheme 必须走 Intent — 经典修复,以及为何崩溃只在登录、支付或分享步骤出现。
- 移动端 WebView 中的反向 Tabnabbing——无 noopener 时 opener 引用可被滥用,且 WebView 可能不套用浏览器默认 — 被打开的页面如何悄悄把你的 opener 重定向到钓鱼页。