Due to security reasons, we can restrict how our page is rendered in frames. It’s worth knowing how this mechanism works not only to defend our users from threats, but also not to be surprised when we want to create something … unusual.
It all started with my pretty weird way of reading Hacker News. One reason is that I often enjoy reading comments more than the article itself. Second is that I enjoy reading “breadth-first” – I first select articles I want to read, open them in new tabs and then I read them one by one when I have a spare minute. For this purpose, I wanted to create my frontend client for HackerNews. There are many of them right now, but neither of them worked exactly the way I wanted. The Hacker News API is publicly available and it’s very easy to make one on your own.
My vision was inspired by a polish news aggregator wykop.pl, which opens links in frames with a bar on top, from where users can access the link’s comments or its score. My first idea was to create a frontend app hosted on Netlify, opening the HN links in frames in a similar manner, but after making the first proof of concept I noticed the first problem …
Some website authors don’t like to have their website put in a frame on some other website and they are perfectly right. There is a good reason not to do so – the threat of XSS attacks is a real deal.
The oldest way to prevent browsers from rendering your website in frames is
X-Frame-Options header. It has 3 possible values –
deny tells, that the website cannot be put into the frame at all,
sameorigin enables to do so only on the website from the very same domain and
allow-from can specify which domains are permitted to render our site in a frame.
This, however, was not enough, as the header was obsoleted by a much more powerful feature.
This is a much more powerful mechanism because it allows specifying restrictions per resource such as fetched stylesheets, scripts, frames and many more. It consists of one header
Content-Security-Policy which is followed by a set of directives separated by semicolons.
For example, to make sure, that our site can be rendered inside a frame on the same domain or on the otherdomain.com, then our header would look like this:
Content-Security-Policy: frame-src 'self' http://otherdomain.com;
To bypass those restrictions in my Hacker News client, I had to modify the headers of the pages rendered in the frame. I couldn’t do this via a frontend application alone, so I’ve made a browser extension, which serves the application and filters the problematic headers. Because those are security hacks, I’m not planning to release it for the public, but you can always check the source code here: https://github.com/konkit/hackernewsclient.