Skip to content
GoogleGHSA-vx62-cvr5-x3p4

Cross-Frame Scripting (XFS) via Background Proxy in Vimium

MediumPublished Sep 1, 2026

### Summary Vimium's background script provides an `openUrlInCurrentTab` message handler that allows content scripts to request a URL to be opened in the current tab. When a `javascript:` URL is provided, the background script uses the `chrome.scripting.executeScript` API to inject and execute the code. However, the background script does not specify a `frameId` in the injection target. According to the Chrome Extension API documentation for Manifest V3, if `frameId` is omitted, the script is injected into the **main frame** by default. Since any frame (including cross-origin iframes) where Vimium is active can send this message to the background script, a compromised content script in a low-privilege subframe can execute arbitrary JavaScript in the high-privilege top-level origin. ### Vulnerability Detail - **Vulnerability Type:** Cross-Frame Scripting (XFS) / Privilege Escalation - **Affected Component:** `background_scripts/tab_operations.js` - **Affected Versions:** Up to 2.4.2 (Manifest V3) ### Severity Medium - This is a medium-severity privilege escalation vulnerability. It does not provide an initial entry point for an attack, but it can be used to significantly increa...

GitHub advisory

Affected versions

PackageAffectedFixed in
Vimium
Product
< 2.4.32.4.3
Details and references

### Summary Vimium's background script provides an `openUrlInCurrentTab` message handler that allows content scripts to request a URL to be opened in the current tab. When a `javascript:` URL is provided, the background script uses the `chrome.scripting.executeScript` API to inject and execute the code. However, the background script does not specify a `frameId` in the injection target. According to the Chrome Extension API documentation for Manifest V3, if `frameId` is omitted, the script is injected into the **main frame** by default. Since any frame (including cross-origin iframes) where Vimium is active can send this message to the background script, a compromised content script in a low-privilege subframe can execute arbitrary JavaScript in the high-privilege top-level origin. ### Vulnerability Detail - **Vulnerability Type:** Cross-Frame Scripting (XFS) / Privilege Escalation - **Affected Component:** `background_scripts/tab_operations.js` - **Affected Versions:** Up to 2.4.2 (Manifest V3) ### Severity Medium - This is a medium-severity privilege escalation vulnerability. It does not provide an initial entry point for an attack, but it can be used to significantly increase the impact of a separate, hypothetical DOM-based XSS flaw within Vimium. If an attacker achieves code execution within a subframe's Vimium context, this flaw allows them to escalate those privileges to the top-level origin, potentially leading to Cross-Site Scripting (XSS) on the parent page. ### Proof of Concept The vulnerable code is located in `background_scripts/tab_operations.js`: ```javascript export async function openUrlInCurrentTab(request) { const urlStr = await UrlUtils.convertToUrl(request.url); // ... if (UrlUtils.hasJavascriptProtocol(urlStr)) { const scriptingArgs = { target: { tabId: request.tabId }, // VULNERABILITY: Omitted frameId func: (text) => { ... }, args: [urlStr], }; // ... chrome.scripting.executeScript(scriptingArgs); } } ``` The `request` object is populated from the `sender` in `background_scripts/main.js`, but `sender.frameId` was previously ignored during the injection phase. ## Reproduction Steps 1. Navigate to a website that embeds a cross-origin iframe (e.g., a page with a YouTube embed or a third-party ad). 2. Open **Chrome DevTools** (`F12`). 3. Go to the **Console** tab. 4. Click the **Execution Context selector** (the dropdown in the top-left of the console, usually showing `top`). 5. Find the entry for the **cross-origin iframe** and select the **Vimium** extension context associated with it (it will be listed under the extension's name). 6. Execute the following payload in the console: ```javascript chrome.runtime.sendMessage({ handler: "openUrlInCurrentTab", url: "javascript:alert('XFS Success! Target Origin: ' + window.location.origin + '\\nLogged from: ' + document.origin)", }); ``` 7. **Success Condition**: An alert dialog will appear. Observe that `window.location.origin` reflects the **top-level page's origin**, proving that the script was successfully proxied from the iframe into the parent frame. ### Further Analysis The background script must explicitly target the frame that originated the request. **Fix:** In `background_scripts/main.js`, `sender.frameId` is captured and passed to the handler. In `background_scripts/tab_operations.js`, the `frameId` is included in the `target` object: ```javascript target: { tabId: request.tabId, frameIds: [request.frameId] } ``` ### Timeline **Date reported**: 2026-07-17 **Date fixed**: 2026-07-22 **Date disclosed**: 2026-09-01 https://github.com/philc/vimium/commit/4427dc6783503c90b5975876f8547588d33c8ee7

Severity from
GitHub (reviewed advisory)

More Google advisories

All Google
Advisory
Google Chrome: improper authorization
Low3.1Sep 2
Google Chrome: spoofing
Medium5.4Sep 2
Google Chrome: information disclosure
Medium5.3Sep 2
Google Chrome: missing authorization
Low3.1Sep 2
Google Chrome: improper authorization
Medium6.5Sep 2
Google Chrome: remote code execution
High8.8Sep 2

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.