Keypoints
- Guardio Labs found a zero-day RCE in Opera’s My Flow feature that lets an attacker execute files on the host OS via a built-in extension.
- The built-in extension (Opera Touch Background) exposes handlers such as OPEN_FILE, DOWNLOAD_FILE, and SEND_FILE that call native APIs (opr.operaTouchPrivate.openFile) and write to ~/Downloads/MyFlow.
- An attacker-controlled extension can use DeclarativeNetRequest to swap flow.opera.com script resources, but production CSP/SRI normally block such injection.
- Historical/forgotten pages on flow.opera.com lacking CSP/SRI allowed script injection, enabling access to the high-permission extension from attacker-controlled code.
- Attack flow: install malicious extension → open vulnerable flow.opera.com asset → simulate device pairing via flow API (/v1/devices, GET_PAIRING_TOKEN, /v1/connect-devices) → use SEND_FILE to create payload locally → trigger OPEN_FILE (requires a user click) to execute.
- Resulting exploit achieves near-instant cross-platform execution; Opera removed the insecure assets after disclosure.
MITRE Techniques
- [T1176] Browser Extensions – Abused extension permissions (DeclarativeNetRequest) to alter requests and inject code into flow.opera.com pages: ‘we can switch it to fetch our own crafted file with a simple rule.’
- [T1105] Ingress Tool Transfer – Downloaded/created arbitrary files on the host using handlers like DOWNLOAD_FILE and SEND_FILE: ‘this.downloadFile(…), this.sendFile(…, data.content, … )’.
- [T1059.007] Command and Scripting Interpreter: JavaScript – Injected and executed JavaScript in the page context to drive the extension and My Flow handlers; vulnerable historical page showed a script tag without integrity: ”.
- [T1203] Exploitation for Client Execution – Leveraged a forgotten Opera-hosted page lacking CSP/SRI to run attacker-controlled code in the opera.com context and reach powerful extension APIs: ‘an unsafe, forgotten, vulnerable to code injection asset’.
- [T1204.002] User Execution: Malicious Link/Click – OPEN_FILE required a click event to execute the local file, shifting the chain to a one-click scenario: ‘triggering the OPEN_FILE operation requires a click event’.
Indicators of Compromise
- [Domain] Opera My Flow domains used in the exploit – flow.opera.com, flow.operacdn.com (and flow.op-test.net referenced in manifest).
- [File / Script] Script assets and local download folder – ext/v1/scripts-1633701575733.js, ext/v1/scripts-1673951285900.js, and files written to ~/Downloads/MyFlow/.
- [API Endpoints] Flow API endpoints used to simulate pairing and transfer – /v1/devices, /v1/connect-devices, and flow.opera.com/v1/connect-devices.
- [Extension Name / Handler] Built-in extension and exposed handlers – ‘Opera Touch Background’ (built-in extension) with handlers OPEN_FILE, DOWNLOAD_FILE, SEND_FILE (seen in port.onMessage listener).
Guardio Labs’ technical procedure focused on abusing Opera’s built-in My Flow extension (Opera Touch Background), which declares externally_connectable for flow.opera.com and exposes high-privilege handlers such as OPEN_FILE, DOWNLOAD_FILE, and SEND_FILE that invoke native APIs (e.g., opr.operaTouchPrivate.openFile) and store/download files into ~/Downloads/MyFlow. Because those extension handlers are accessible from pages under Opera-controlled domains, attacker-controlled script running in that domain can call the handlers to create arbitrary files on disk and request their execution.
To get code executing in the Opera-controlled context despite production CSP and SRI protections, the researchers located archived/forgotten flow.opera.com pages lacking CSP/SRI. A malicious (or maliciously-updated) Chrome-style extension with DeclarativeNetRequest permission can replace requested script resources or open the vulnerable page to inject JavaScript. The extension then simulates a My Flow pairing (POST /v1/devices to get DEVICE ID and TOKEN, GET_PAIRING_TOKEN for QR value, and POST to /v1/connect-devices to pair), and uses SEND_FILE to save a crafted blob to the MyFlow download folder, avoiding complex encryption steps by directly creating the payload file.
Finally, the exploit triggers the OPEN_FILE handler to execute the payload; Opera enforces that OPEN_FILE must be triggered from a click event, so the chain requires a single user click (one-click execution). The combined technique—extension-driven request manipulation, exploitation of legacy Opera-hosted assets without CSP/SRI, use of high-privilege built-in extension handlers to write files, and a click-gated native open—enables near-instant cross-platform execution. Opera removed the insecure assets after disclosure.