← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-11287 · CWE-20 · Disclosed 2026-06-05

Insufficient policy enforcement in Navigation in Google Chrome on Android prior to 149

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a bad lock on an interior door, not a busted front gate

CVE-2026-11287 is an Android Chrome navigation-policy bug, fixed in 149.0.7827.53, where a crafted HTML page can help an attacker *who already compromised the renderer process* bypass navigation restrictions. The affected population is Chrome on Android versions earlier than 149.0.7827.53; public release notes show Android 149.0.7827.48 shipped just before the fix, and older stable builds such as 148.0.7778.215 were also in the vulnerable range until the 149 branch picked up the corresponding security fixes.

The vendor-style 6.5 / MEDIUM score overstates enterprise urgency because it scores the bug like a remotely reachable web issue, while the plain-language description hides the real gate: the attacker must first land a separate renderer compromise. Chromium itself tagged the issue as *Low*, and that matches reality better for defenders managing fleets. This is a defense-in-depth break in an exploit chain, not a stand-alone foothold.

"This is a chain extender, not an entry point: it only matters after renderer compromise on Android Chrome."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Lure the user to attacker content

The attacker needs a target using Chrome for Android below 149.0.7827.53 to load attacker-controlled HTML. The delivery vehicle is trivial — any malicious site, ad slot, or redirect can host the page — but this CVE does nothing by itself at this stage.
Conditions required:
  • Victim uses Chrome on Android <149.0.7827.53
  • Victim loads attacker-controlled web content
  • User interaction is required by the CVSS model (UI:R)
Where this breaks in practice:
  • Android-only population narrows exposure versus desktop Chrome
  • Managed mobile fleets often auto-update through Google Play within about a day once policy conditions are met
  • This step alone produces no impact from CVE-2026-11287
Detection/coverage: Standard vuln scanners rarely see mobile app patch levels well; this is mostly an MDM / EMM inventory problem, not a network scan problem.
STEP 02

Chain in a separate renderer exploit

The attacker must already have compromised the Chrome renderer process using some *other* bug or exploit primitive. In practice that means a memory-corruption or logic flaw elsewhere in Blink/V8/Skia or a pre-existing exploit chain; CVE-2026-11287 is not an initial-access bug.
Conditions required:
  • A separate renderer compromise primitive is available
  • Exploit reliability works on Android/ARM for the target build
  • The attacker can execute the chain inside the browser sandbox context
Where this breaks in practice:
  • This is the decisive friction: prior compromise is mandatory
  • No public PoC for this CVE was found in source review
  • Modern browser mitigations and exploit reliability issues make chained browser exploitation non-trivial
Detection/coverage: Crash telemetry, Safe Browsing signals, and browser exploit detections may catch the precursor bug, but mobile endpoint visibility is usually weaker than desktop EDR.
STEP 03

Bypass navigation restrictions with crafted HTML

Once renderer control exists, the attacker uses the crafted page to abuse insufficient policy enforcement in Navigation and reach a state the browser should have blocked. The public bug details are still restricted, but the advisory and NVD description are consistent that this is a navigation-restriction bypass, not code execution.
Conditions required:
  • Renderer is already compromised
  • The exploit chain can exercise the vulnerable navigation path on Android
  • The target build still enforces the old buggy policy logic
Where this breaks in practice:
  • Restricted Chromium issue details limit easy copycat weaponization
  • Exact exploitability likely depends on specific navigation state and page structure
  • Impact is bounded to what the bypass enables inside the broader chain
Detection/coverage: There is no reliable network signature for 'policy enforcement bypass in Navigation'; browser forensic artifacts and exploit-chain telemetry matter more than signature scanning.
STEP 04

Turn the bypass into integrity impact

The stated CVSS impact is integrity-only, which fits a scenario where navigation controls are subverted to load or influence content that should not be reachable. That can strengthen a broader exploit chain, but the CVE by itself does not advertise direct data theft, sandbox escape, or device takeover.
Conditions required:
  • A meaningful restricted-navigation target exists in the attack chain
  • The attacker can capitalize on the bypass before the browser is restarted or updated
Where this breaks in practice:
  • No standalone confidentiality or availability impact is documented
  • Blast radius is one browser instance on one device at a time unless paired with other bugs
  • Enterprise risk depends heavily on whether you already care about mobile browser exploit chains
Detection/coverage: Best coverage is indirect: managed-play version inventory, browser crash spikes, and incident telemetry for suspicious mobile web sessions.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public exploitation evidence found in the reviewed sources, and it is not in CISA KEV as of 2026-06-06.
Public PoC statusNo public PoC or weaponized repo was found in source review. The Chromium bug reference remains effectively opaque from public search, which raises friction for opportunistic attackers.
EPSS0.00019 from the user-supplied intel, which is extremely low. The exact percentile was not independently verified from an authoritative EPSS query during this assessment.
KEV statusAbsent from the CISA KEV catalog; no KEV date applies.
CVSS vector reality checkCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N captures remote delivery and user interaction, but it does not price in the decisive prerequisite: prior renderer compromise.
Affected versionsChrome on Android <149.0.7827.53. Public Android release notes show 149.0.7827.48 was released just before the fixed train.
Fixed versionsUpgrade Chrome on Android to 149.0.7827.53 or later. Google also notes Android releases inherit the corresponding desktop security fixes unless otherwise noted.
Disclosure timelineReported by Google on 2026-04-13 in Chrome release notes; desktop stable 149.0.7827.53 shipped on 2026-06-02; NVD published the CVE on 2026-06-04 and shows a CISA-ADP update on 2026-06-05.
Exposure / scanning realityThis is not an internet-scannable service. Shodan, Censys, and FOFA are basically irrelevant; exposure is whatever portion of your Android fleet is still below the fixed Chrome version.
Researcher / sourceReported by Google according to Chrome release notes; Chromium rated it Low even though the CISA-ADP CVSS entry shows 6.5 / MEDIUM.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.4/10)

The single biggest downgrading factor is that exploitation requires a pre-existing renderer compromise, which makes this post-exploitation inside the browser rather than a practical initial-access path. That sharply narrows the real attacker population, the reachable victim set, and the number of enterprise incidents this CVE will drive on its own.

HIGH Severity downgrade driven by mandatory prior renderer compromise
MEDIUM Impact interpretation given restricted Chromium bug details
HIGH Patch-level identification of vulnerable Android Chrome versions

Why this verdict

  • Major prerequisite drag: the attacker must have already compromised the renderer process, so this CVE is chain-dependent rather than a front-door exploit.
  • Population is narrower than generic Chrome CVSS implies: Android-only exposure cuts the enterprise blast radius relative to desktop/browser-wide scoring assumptions.
  • No exploitation heat: no KEV listing, no public PoC found, and the supplied EPSS is near-zero, so there is no evidence this is attracting real-world attacker attention.
  • Impact is bounded: published scoring shows integrity-only impact with no documented direct confidentiality loss, availability loss, or sandbox escape from this bug alone.
  • Modern controls help at earlier stages: Safe Browsing, web filtering, Play auto-updates, and exploit mitigations mostly act on the precursor exploit stage, which is exactly where this chain is fragile.

Why not higher?

If this were a stand-alone remote browser exploit, a sandbox escape, or something already in active chains, the score would jump fast. But a vulnerability that only matters after renderer compromise is already one layer deep into an exploit path, and that is real-world downward pressure you should honor.

Why not lower?

It still sits in a highly exposed client surface — the mobile browser — and policy-bypass bugs can absolutely matter when paired with another browser flaw. So this is not IGNORE: it deserves routine patching and fleet verification, just not special-emergency treatment.

05 · Compensating Control

What to do — in priority order.

  1. Enforce Chrome auto-updates on managed Android — Use managed Google Play / Android Enterprise policy to make sure Chrome can update automatically and is not stuck behind charging, Wi-Fi, or idle constraints. For a LOW verdict there is no SLA clock, but do this in the next normal mobile hygiene cycle so vulnerable 149.0.7827.48 and older builds age out quickly.
  2. Inventory Chrome versions from MDM — Pull package/version data for com.android.chrome and identify devices below 149.0.7827.53. For LOW, this is backlog hygiene rather than emergency response, but you want a clean target list before the next routine compliance review.
  3. Reduce browser exploit-chain exposure — Keep Safe Browsing, web filtering, and malicious-site blocking enabled because they can disrupt the *precursor renderer exploit* this CVE depends on. That matters more than trying to detect this specific navigation bug, and it should remain a standing control for all managed devices.
  4. Prefer current stable channel only — Avoid version lag and unmanaged alternate channels on enterprise Android fleets unless testing requires them. For LOW, align this during the next regular app-governance pass rather than treating it as a break-glass action.
What doesn't work
  • A WAF or perimeter IPS does not meaningfully solve this; the vulnerable surface is a local mobile browser processing attacker content, not an exposed enterprise web service.
  • MFA is irrelevant to the browser bug itself; it may protect downstream accounts, but it does not stop a compromised renderer from exercising the vulnerable navigation path.
  • Network scanning will not find this reliably because the issue lives in a client app version on Android devices, not in an internet-facing daemon.
06 · Verification

Crowdsourced verification payload.

Run this on an auditor workstation against a CSV export from your MDM/EMM or asset inventory, not on the Android handset itself. Invoke it as python3 check_cve_2026_11287.py devices.csv --package-column package --version-column version with no special privileges; it outputs VULNERABLE, PATCHED, or UNKNOWN and returns exit code 1, 0, or 2 respectively.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_cve_2026_11287.py
# Determine exposure to CVE-2026-11287 from an inventory CSV.
# Expected input: a CSV containing at least a package column and a version column.
# Default package name checked: com.android.chrome
# Exit codes:
#   0 = PATCHED
#   1 = VULNERABLE
#   2 = UNKNOWN

import argparse
import csv
import re
import sys
from typing import List, Optional, Tuple

FIXED_VERSION = "149.0.7827.53"
DEFAULT_PACKAGE = "com.android.chrome"


def parse_version(v: str) -> Optional[Tuple[int, ...]]:
    if v is None:
        return None
    parts = re.findall(r"\d+", v)
    if not parts:
        return None
    return tuple(int(p) for p in parts)


def cmp_version(a: str, b: str) -> Optional[int]:
    va = parse_version(a)
    vb = parse_version(b)
    if va is None or vb is None:
        return None
    max_len = max(len(va), len(vb))
    va = va + (0,) * (max_len - len(va))
    vb = vb + (0,) * (max_len - len(vb))
    if va < vb:
        return -1
    if va > vb:
        return 1
    return 0


def main() -> int:
    ap = argparse.ArgumentParser(description="Check inventory CSV for CVE-2026-11287 exposure")
    ap.add_argument("csv_file", help="Path to inventory CSV export")
    ap.add_argument("--package-column", default="package", help="CSV column containing package name (default: package)")
    ap.add_argument("--version-column", default="version", help="CSV column containing installed version (default: version)")
    ap.add_argument("--device-column", default="device", help="CSV column containing device identifier (default: device)")
    ap.add_argument("--package-name", default=DEFAULT_PACKAGE, help="Android package name to evaluate (default: com.android.chrome)")
    args = ap.parse_args()

    vulnerable: List[str] = []
    patched: List[str] = []
    unknown: List[str] = []
    found_rows = 0

    try:
        with open(args.csv_file, newline="", encoding="utf-8-sig") as fh:
            reader = csv.DictReader(fh)
            if reader.fieldnames is None:
                print("UNKNOWN - CSV has no header row")
                return 2

            required = {args.package_column, args.version_column}
            missing = [c for c in required if c not in reader.fieldnames]
            if missing:
                print(f"UNKNOWN - missing required column(s): {', '.join(missing)}")
                return 2

            for row in reader:
                pkg = (row.get(args.package_column) or "").strip()
                if pkg != args.package_name:
                    continue

                found_rows += 1
                device = (row.get(args.device_column) or f"row-{found_rows}").strip()
                ver = (row.get(args.version_column) or "").strip()
                result = cmp_version(ver, FIXED_VERSION)

                if result is None:
                    unknown.append(f"{device}:{ver or 'NO_VERSION'}")
                elif result < 0:
                    vulnerable.append(f"{device}:{ver}")
                else:
                    patched.append(f"{device}:{ver}")

    except FileNotFoundError:
        print(f"UNKNOWN - file not found: {args.csv_file}")
        return 2
    except Exception as exc:
        print(f"UNKNOWN - failed to process CSV: {exc}")
        return 2

    if found_rows == 0:
        print(f"UNKNOWN - no rows found for package {args.package_name}")
        return 2

    if vulnerable:
        print("VULNERABLE")
        print(f"fixed_version={FIXED_VERSION}")
        print(f"vulnerable_count={len(vulnerable)}")
        print(f"patched_count={len(patched)}")
        print(f"unknown_count={len(unknown)}")
        for item in vulnerable[:50]:
            print(item)
        if len(vulnerable) > 50:
            print(f"... {len(vulnerable) - 50} more vulnerable devices omitted")
        return 1

    if unknown and not patched:
        print("UNKNOWN")
        print(f"fixed_version={FIXED_VERSION}")
        print(f"unknown_count={len(unknown)}")
        for item in unknown[:50]:
            print(item)
        if len(unknown) > 50:
            print(f"... {len(unknown) - 50} more unknown devices omitted")
        return 2

    print("PATCHED")
    print(f"fixed_version={FIXED_VERSION}")
    print(f"patched_count={len(patched)}")
    print(f"unknown_count={len(unknown)}")
    if unknown:
        print("note=some devices had unparseable versions; review separately")
        for item in unknown[:50]:
            print(item)
        if len(unknown) > 50:
            print(f"... {len(unknown) - 50} more unknown devices omitted")
    return 0


if __name__ == "__main__":
    sys.exit(main())
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not elevate this into an emergency campaign. Pull your managed Android inventory for com.android.chrome, identify anything below 149.0.7827.53, and let managed Google Play/EMM updates clear it in the next normal mobile patch cycle; because this is LOW, there is no noisgate mitigation SLA and effectively no noisgate remediation SLA beyond backlog hygiene, so document the chain-dependent nature of the bug and close it during routine browser version maintenance rather than interrupting higher-value patch work.

Sources

  1. NVD entry for CVE-2026-11287
  2. Chrome stable channel update for Desktop 149.0.7827.53
  3. Chrome for Android early stable 149.0.7827.48 release
  4. Chrome for Android stable 148.0.7778.215 release
  5. CISA Known Exploited Vulnerabilities Catalog
  6. Android Enterprise app update behavior
  7. Manage Chrome browser on Android devices
  8. Update Google Chrome on Android
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.