Three separate XHR oddities I found while exploring how Internet Explorer’s Microsoft.XMLHTTP ActiveX object handled unusual situations. None of them alone was a dramatic vulnerability, but together they illustrated how the security model around XHR had some interesting grey areas.
1. XHR Created Inside about:blank
If you create a Microsoft.XMLHTTP object via execScript inside an about:blank iframe, the resulting object inherits the about:blank origin — which IE effectively treated as the same domain as the parent. This meant the object could make requests that appeared to bypass the same-origin check.
<!-- aboutBlank/index.html -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Creation inside about:blank</title></head>
<body>
<iframe name="ifr" src="about:blank"></iframe>
<script language="JavaScript">
window.sChange = function()
{
if (oXML.readyState == 4)
{
alert("If we create the object inside an about:blank URL, it consider that to be the domain: \n\n" + oXML.responseText);
}
}
// Create it inside an about:blank
ifr.execScript('parent.oXML = new ActiveXObject("Microsoft.XMLHTTP")');
oXML.onreadystatechange = sChange;
oXML.open("GET", "blank", true);
oXML.send(null);
</script>
</body>
</html>
2. Multiple Redirects Across Domains
If the request followed a chain of redirects and one of the intermediate hops was on a different domain, IE would silently return an empty responseText rather than raising an error. This made it hard to detect certain redirect-based attacks.
<!-- multipleRedirects/index.html -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Multiple Redirects</title></head>
<body>
<script language="JavaScript">
window.sChange = function()
{
if (oXML.readyState == 4)
{
alert("If one of the redirects is on a different domain, this will be empty: \n" + oXML.responseText);
}
}
oXML = new ActiveXObject("Microsoft.XMLHTTP");
oXML.onreadystatechange = sChange;
oXML.open("GET", "mRedir.asp", true);
oXML.send(null);
</script>
</body>
</html>
3. responseXML Object Not Destroyed After Reuse
When you called open and send again on the same XMLHTTP object to load a new XML document, the previous responseXML object was not garbage collected. A cached reference to it remained valid and continued to reflect the first document’s content even after the object had been reloaded.
<!-- responseXML_not_destroyed/index.html -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>responseXML object not destroyed</title></head>
<body>
<h1>responseXML object not destroyed</h1>
<script language="JavaScript">
var oXML = new ActiveXObject("Microsoft.XMLHTTP");
oXML.open("GET", "1.xml", false);
oXML.send(null);
// We save a pointer to the responseXML object;
var cached_responseXML = oXML.responseXML;
// Now we load a different XML inside that same object...
oXML.open("GET", "2.xml", false);
oXML.send(null);
// But here we can see that both (the cached and new one) are accessible
alert(cached_responseXML.xml + "\n\n" + oXML.responseXML.xml);
</script>
</body>
</html>
The responseXML lifetime issue was the most interesting to me — it suggested that the underlying COM object’s reference counting wasn’t properly handling the reuse case, and in certain multi-request scenarios you could end up with stale XML content that the application mistakenly treated as fresh. The about:blank creation path was also worth noting because it showed a zone/origin inheritance assumption that didn’t always hold.
Found during my years at Microsoft (2006–2014). These bugs were patched long ago — shared here as a historical record for learning purposes.