Headline
CVE-2020-12079: Critical security issue [solved in 0.8.9] [CVE-2020-12079] · Issue #1519 · beakerbrowser/beaker
Beaker before 0.8.9 allows a sandbox escape, enabling system access and code execution. This occurs because Electron context isolation is not used, and therefore an attacker can conduct a prototype-pollution attack against the Electron internal messaging API.
Post mortem on this issue
First I want to say, thank you so much to @imagemlt for researching and privately disclosing this issue. They were extremely helpful, clear, and generous with their time.
Beaker uses Electron/Chromium’s tools to sandbox every tab from the rest of the system. Like other browsers, this sandbox exists at two levels: the Web Platform sandbox which only provides safe APIs, and the process sandbox which restricts any kind of operations if the Web Platform sandbox were penetrated. Web API calls are translated into messages to Beaker’s internal processes which then apply permissions and handle their requests.
When a page loads, Beaker use’s an Electron feature called the “preload script” to inject its custom Web APIs (e.g. the Hyperdrive API). These APIs are effectively wrappers around inter-process messaging channels. The preload script environment provides Electron APIs for accessing the channels, and then removes those APIs once the page loads.
For added security, Electron provides a “context isolation” flag for the preload script which ensures that the page could never access those messaging-channel-APIs directly. I incorrectly believed that no other messaging channel existed other than the ones documented by those APIs. Therefore I assumed that, even if a page was able to access the Electron APIs exposed in the preload script, it would not be possible to craft a message that could cause an issue – that it would be similar to using the Web APIs we normally expose. Therefore, I did not enable the context isolation flag.
To be clear: this was a mistake on my part. The Electron team has explicitly advised all developers to use context isolation and I ignored that advice. I apologize for that. I wasn’t familiar enough with the internal details of Electron to go against the advice, and that’s why this exploit was possible. This was my fault.
It turns out that Electron has its own messaging channel which is not normally accessible, but which can be accessed by polluting the Function prototype chain. @imagemlt was able to use a prototype-pollution attack to access Electron’s internal messaging API. They then spawned a new page with all of the web-platform protections disabled, which enabled them to freely exit the sandbox – which they proved by spawning calculator.app.
Solving this was straight-forward: I turned on context isolation and then used Electron’s contextBridge API to safely expose our Web APIs to the page. This makes a prototype-pollution attack infeasible, and closes the security hole.
Be sure to use only Beaker 0.8.9 and above to stay protected from this attack.
Going forward, I will be checking and rechecking Beaker against Electron’s security guidelines. I also intend to learn about Electron’s internal messaging channel and investigate whether my original assumption – that no dangerous messages can be constructed – can be made true.
Thanks again to @imagemlt for responsibly disclosing this issue, and also to the Electron team for the excellent tools and guidance they provide for security. If anybody has any followup questions or concerns, feel free to ask them here or by email.