iFrame — A love story

Max Rafferty
Slices of Bread
Published in
7 min readApr 13, 2020
John Lee / Bread Finance © (All Rights Reserved)

This article is the first in a series about working with iFrames.

Our wonderful team at Bread Finance has built a robust pay-over-time payments platform over the last six years, and our checkout integrations are powered at their core by the inline frame (iFrame) element. Bread’s flexible, convenient, and whitelableable solutions depend on the iFrame to provide security and control, but the iFrame’s many quirks have given many opportunities for the team to develop an expertise around working with them. While modern tooling like the open source Zoid suite from our friends over at PayPal can ease these challenges, our complex and nuanced needs require absolute control of the embedded frames we have built our application upon. I encourage readers to explore the series that dives into how many iFrame challenges have been abstracted away, but if this leaves you wondering about the technical nitty-gritty, join us as we take a look at how iFrames are wrangled at Bread.

•✧─────────────✧¸.•´*¨`*•✿•*`¨*`•.¸✧─────────────✧•

To kick things off, we need to answer a few fundamental questions: what makes iFrames so unique (and weird, and dangerous!), and given all that, why would we choose to hitch our train to them as a fundamental part of our technology? To really understand what is going on, we’ll need to dive into a little bit of the history of the element and its original intended uses. We’ll then look at how the landscape of embeddable applications set into the options we have today, and what the advantages and disadvantages of each of these approaches is. Ultimately we’ll want to answer why the iFrame is the safest and best answer to Bread’s unique set of requirements.

So then, what’s up with them there frames?

Markus Trienke / CC BY-SA (https://creativecommons.org/licenses/by-sa/2.0)

The humble inline frame. We have asked a lot of this element that quietly snuck onto the stage in 1994; At that time its only purpose was to play cleanup for its sibling elements, the FrameSet and Object tags. At this time, the primary use case for frames was to hold common page elements, such as navigation, in order to reduce the usage of precious bandwidth over dial-up. IFrame saw some use in guestbooks and other small applications where we wanted to target the frame for navigation purposes, but overall they played third fiddle. It should be noted that at this time even the specification is not especially clear about when one frame should be chosen over another, citing “different content models”. The early web was a different time, and for context the iFrame predates even a full implementation of CSS (2000’s IE5 for Mac, go figure!) We’ll want to keep these humble roots in mind when we examine the iFrame, and its quirks, in a modern light.

Things got interesting once the ad-men got their hands on our humble frame. Enter the late 90s: the dot com bubble was inflating, as was the desire for a more robust cross-domain application controls. So too was the iFrame specification inflating, with the HTML5 iFrame section exploding from from six sentences to eleven and a half pages. There were no more clarifying articles on when to use Object and iFrame, iFrame was for documents that needed cross-domain communication with the host page, and Object was for applets, specifically Flash (and what about that fancy new embed tag?). Sibling elements Frame and FrameSet went the way of the Marquee, and so iFrame had to carry their burdens as well. The rising ubiquity of advertising and user tracking guaranteed a continued need for cross-domain scripting. This culminated in the mid-aught appearance of the postMessage standard and cemented the iFrame as a key tool in the web-dev’s kit. A humble element no longer.

Why choose to use iFrame?

National Photo Company Collection, restored by Adam Cuerden / Public domain

At Bread, an embedded application for completing an eCommerce transaction has a number of important considerations, with security being the absolute top of the list. We’ll discuss “sandboxability” as we consider the various embedding options, meaning the ability to operate an application in total isolation from the page on which it lives. This property is crucial to prevent attackers from taking control of our merchant partners’ pages via techniques like script injection, cross-site scripting (XSS), or man-in-the-middle (MitM), which would allow attackers to watch as users enter their personal info into our application. In the reverse, we also need to be able to bridge across the sandbox boundary securely in order to transmit data like the status of an order or transaction back to our partner’s eCommerce platform so that the order can actually be completed. Not all platforms expose HTTP APIs for this purpose, and so direct communication between host page and embedded app is a requirement. Doing this messaging securely is not trivial, and we’ll dig into this topic deeply in a later article. Last, because Bread allows for white label customization of our financing products, we can’t make assumptions about how they will look until render-time. This last requirement is surprisingly difficult to guarantee consistency around because of cascading styles, and so we’ll consider “style-sandboxing” as its own beneficial property independent of data-sandboxing.

We’ve mentioned a number of embedding options thus far. Of immediate consideration are the iFrame, Object, and Embed tags, all of which can load HTML documents and run scripts internally. The least dynamic embedding option is the image tag, which while limited also has its advantages (specifically speed, which we will discuss in later articles on performance in this series). Flash, while technically still possible to embed, is not a viable option in production these days due to the security concerns that killed it in the first place. More Javascript-forward solutions like HTML canvas & WebGL, web components, and Webassembly are also tantalizing options for sandbox-like applications. Lets dig into the pros and cons of each, in approximate order of viability of each of these for the purposes of an embedded application like Bread’s:

  • Images: Images have a place in our embedding toolkit because they are dead simple and fast as hell. Image loading is prioritized by browsers, and browsers are optimized specifically to quickly decompress and render images quickly. Images are, of course, not themselves applications and so cannot be the only tool we use to build our application with respect to data collection, as they have no sandboxability. That said, dynamically generated images paired with image maps provide a surprisingly flexible tool for stylistic sandboxing. Dynamic data-URIs and serverside headless-browser generated images are topics worthy of their own articles, but these are performance optimizations rather than applications in and of themselves.
  • Canvas/WebGl: Another very interesting and unique element, the canvas lets us “draw” whatever we like to the screen. Paired with WebGL, we can create any sort of application we desire, free from the constraints of HTML and CSS, exactly the way we would create a desktop application. However, at its core, we’re still running on the host-page’s Javascript thread, and so this approach (while very fun), is no bueno from a sandboxing perspective. WebGL is also not supported in any IE, which eliminates it from Bread’s use case.
  • The Embed and Object tags: These tags exist for embedding multimedia into pages like videos and PDFs. The Embed tag has fallen somewhat out of favor recently, as Object is capable of displaying any file type browsers support. Both have identical properties from the perspective of an embedded application. These tags have the advantage of being prioritized by the browser differently than iFrames, making them somewhat faster to their initial render, but neither supports cross domain messaging back to the host page. This could be worked around via CORS APIs on our own backend, but that is a very roundabout solution, the downsides of which likely outweigh the performance gains.
  • Web Components: One of the more exciting upcoming web standards (if you’re like myself and that’s your thing), the web components standard enables the creation of custom HTML elements. You can think of them as native React elements, if that makes things clearer. The most important feature of native web components is that they have completely isolated backing Javascript and CSS, which protects them from JS global namespacing issues and CSS’ cascade. Unfortunately, in the current state of the world, these components are not true black boxes, and there are backdoors into the components from the host page. While these are very useful and very nearly supported in all modern browsers, they cannot be relied upon for security sensitive applications.
  • Webassembly: This is a technology that is very exciting and viable for the purposes of sandboxing, but currently the browser support is spotty. Webassembly is a native browser API for executing applications written in any language, and compiled down to the Webassembly bytecode. I’m currently not aware of any programmatic backdoors into the Webassembly black box, which makes me hopeful that this rising standard could be a candidate for creating secure data collection applications. Watch this technology as browser support increases.

While I am sure this is far from an exhaustive list, we arrive at the reasons we would want to tackle the challenge of utilizing iFrames after exhausting the possible alternatives. The nearly 30 year old iFrame standard certainly has barbs in its API that any piece of technology entering middle age will have (we should all be so lucky!), but for security conscious, whitelabelable applications we have no other choice. Fortunately, this is well understood by the various standards committees, and so while third party cookie policies restrict further month after month, the iFrame remains a viable and important tool that we need to understand — at least until the portals standard is finalized.

Up next: iFrame performance

We’re hiring! If you’re interested in learning more about what it’s like to work at Bread, please check out our website and Life at Bread page, and if you’re interested in joining our growing team, feel free to visit our current openings for a list of all open positions!

--

--