AdSense in a sandboxed IFRAME

2014-12-29 00:00:00 +0000


Google AdSense is a convenient way to recover at least part of the hosting costs on a blog or community website, but a security counscious webmasters will be always a bit uncomfortable about embedding third party JavaScript in their websites. The moral compromise associated with advocating web security and hosting third party ads at the same time is a well known challenge indeed. There actually were some proposals to introduce a hardened subset of JavaScript for that purpose, but they didn’t seem to work. In the world where we’re living what you actually get is usually a minified or obfuscated piece of JavaScript that essentially loads stuff from places. Lots of stuff from many places.

AdSense snippet assigned to a publisher by Google dynamically creates an iframe that loads actual advertisement content – JavaScript, images or Flash applications – and makes various maintenance calls. On my pages a single AdSense snippet results in 5-10 further calls to download static content (JS, SWF, PNG) and XHR calls to Google API. In most cases this will be probably harmless and to some extent screened by Google, but still there must be a way of keeping it separate from the code you have written yourself.

HTML5 IFRAME sandbox attribute seems to be exactly what we’re looking for. After some experiments I was able to come up with a way of placing all AdSense code in a sandboxed IFRAME which will limit some risks from the embedded third party code. This can get a bit tricky, especially with responsive AdSense snippets, as they need a way of determining their dimensions in relation to the main window.

While this may violate AdSense terms of service that explicitly forbid placing ads in IFRAME due to different forms of abuse, Google admits that there may be legitimate scenarios for their usage so you can ask for their authorisation on per-case basis. Since you can’t really contact them for approval before they tag your for alleged violation, I wouldn’t worry too much about that.

This is the code for a minimalistic HTML page creating IFRAME which then loads AdSense. Note the styling: the IFRAME is invisible, spanning to the whole width of the main window:

<!DOCTYPE html>
<html>
<head><title>Test</title>
<style>
body { text-align: center; }
#adsense {
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    margin: 0;
    overflow: hidden;
}
</style>
</head>

<body>
<h1>AdSense test</h1>

<iframe id="adsense" src="adsense.html" sandbox="allow-same-origin allow-forms allow-scripts">

</body>
</html>

From all the available IFRAME sandbox attributes allow-same-origin allow-forms allow-scripts seem to be required for AdSense to work properly.

Then there’s the actual framed document adsense.html which contains just the original snippet as copied from AdSense console:

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- TestCSP -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-8618780985613063"
     data-ad-slot="5484345690"
     data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

This is how it looks like:

AdSense in an IFRAME

A further improvement would be to add a separate Content Security Policy header to the adsense.html document. In such case the IFRAME tag would not actually need the sandbox attribute because it could be announced in the CSP header itself.