Google Chrome & Iframe `allow` Permissions Problems – CodePen

0
10


If you’re a CodePen user, this shouldn’t affect you aside from potentially seeing some console noise while we work this out. Carry on!

At CodePen we have Embedded Pens which are shown in an <iframe>. These contain user-authored code at a non-same-origin URL as where they are placed. We like to be both safe and as permissive as possible with what we allow users to build and test.

The sandbox attribute helps us with safety and while there are some issues with it that we’ll get to later, this is mostly about the allow attribute.

Here’s an example.

A user wants to use the navigator.clipboard.writeText() API. So they write JavaScript like:

button.onclick = async () => {
  try {
    await navigator.clipboard.writeText(`some text`);
    console.log('Content copied to clipboard');
  } catch (err) {
    console.error('Failed to copy: ', err);
  }
}

The Embedded Pen is placed on arbitrary origins, for example: chriscoyier.net. The src of the <iframe> is at codepen.io, so there is an origin mismatch there. The JavaScript in the iframe is not same-origin JavaScript, thus is subject to permissions policies.

If CodePen were to not use the allow attribute on our <iframe> it would throw an error when the user tries to execute that JavaScript.

This is an easy fix. We make sure that allow attribute is on the <iframe>, like this, targeting the exact feature we want to allow at any origin:

<iframe
  src="https://codepen.io/..." 
  allow="clipboard-write *;">
</iframe>

But here’s where the problem comes in…

The (new) Nested Iframe Issue

CodePen has Embedded Pens are actually nested <iframe>s in a structure like this:

In code structured like this:

<iframe src="https://codepen.io/...">
  CodePen UI

  <iframe src="https://blog.codepen.io/2025/10/20/google-chrome-iframe-allow-permissions-problems/...">
    User-Authored Code
  </iframe>
</iframe>

We need to put the allow attribute on the user-authored code, so it works, like this:

<iframe src="https://codepen.io/...">
  CodePen UI

  <iframe 
     src="https://blog.codepen.io/2025/10/20/google-chrome-iframe-allow-permissions-problems/..." 
     allow="clipboard-write *;"
  >
    User-Authored Code
  </iframe>
</iframe>

This is the problem!

As soon as the nested iframe has the allow attribute, as of recently (seems like Chrome 136) this will throw an error:

With our complete list (which I’ll include below), this error list is very intense:

Error messages in a developer console indicating various permissions policy violations for different APIs.

Can’t we just put the allow attributes on both <iframe>s?

Yes and no.

Now we run into a second problem that we’ve been working around for many years.

That problem is that every browser has a different set of allow attribute values that is supports. If you use a value that isn’t supported, it throws console errors or warnings about those attributes. This is noisy or scary to users who might think it’s their own code causing the issue, and it’s entirely outside of their (or our) control.

The list of allow values for Google Chrome

We know we need all these to allow users to test browser APIs. This list is constantly being adjusted with new APIs, often that our users ask for directly.

<iframe
  allow="accelerometer *; bluetooth *; camera *; clipboard-read *; clipboard-write *; display-capture *; encrypted-media *; geolocation *; gyroscope *; language-detector *; language-model *; microphone *; midi *; rewriter *; serial *; summarizer *; translator *; web-share *; writer *; xr-spatial-tracking *"
></iframe>

There are even some quite-new AI-related attributes in there reflecting brand new browser APIs.

Example of allow value errors

If were to ship those allow attribute values on all <iframe>s that we generate for Embedded Pens, here’s what it would look like in Firefox:

A list of unsupported feature policy warnings displayed in a console log, indicating various feature names that are not recognized or supported.
At the moment, Firefox actually displays three sets of these warning. That’s a lot of console noise.

Safari, at the moment, isn’t displaying errors or warnings about unsupported allow attribute values, but I believe they have in the past.

Chrome itself throws warnings. If I include an unknown policy like fartsandwich, it will throw a warning like:

Those AI-related attributes require a trial which also throw warnings, so most users get that noise as well.

Error messages displayed in a console related to unsupported origin trials and unrecognized features.

We (sorry!) Need To Do User-Agent Sniffing

To avoid all this noise and stop scaring users, we detect the user-agent (client-side) and generate the iframe attributes based on what browser we’re pretty sure it is. Here’s our current data and choices for the allow attribute

export default {
  allowAttributes: {
    chrome: [
      'accelerometer',
      'bluetooth',
      'camera',
      'clipboard-read',
      'clipboard-write',
      'display-capture',
      'encrypted-media',
      'geolocation',
      'gyroscope',
      'language-detector',
      'language-model',
      'microphone',
      'midi',
      'rewriter',
      'serial',
      'summarizer',
      'translator',
      'web-share',
      'writer',
      'xr-spatial-tracking'
    ],
    firefox: [
      'camera',
      'display-capture',
      'geolocation',
      'microphone',
      'web-share'
    ],
    default: [
      'accelerometer',
      'ambient-light-sensor',
      'camera',
      'display-capture',
      'encrypted-media',
      'geolocation',
      'gyroscope',
      'microphone',
      'midi',
      'payment',
      'serial',
      'vr',
      'web-share',
      'xr-spatial-tracking'
    ]
  }
};

We’ve been around long enough to know that user-agent sniffing is rife with problems. And also around long enough that you gotta do what you gotta do to solve problems. We’ve been doing this for many years and while we don’t love it, it’s mostly worked.

The User-Agent Sniffing Happens on the Client

<script>
  /*
    We need to user-agent sniff at *this* level
    so we can generate the allow attributes
    when the iframe is created.
  */
</script>
<iframe src="https://blog.codepen.io/2025/10/20/google-chrome-iframe-allow-permissions-problems/..." allow="https://blog.codepen.io/2025/10/20/google-chrome-iframe-allow-permissions-problems/..."></iframe>

CodePen has a couple of features where the <iframe> is provided directly, not generated.

  1. Direct <iframe> embeds. Users choose this in situations where they can’t run JavaScript directly on the page it’s going (e.g. RSS, restrictive CMSs, etc)
  2. oEmbed API. This returns an <iframe> to be embedded via a server-side call.

The nested structure of our embeds has helped us here where we have that first level of iframe to attempt to run the user-agent sniff an apply the correct allow attributes to the internal iframe.

The problem now is that if we’re expected to provide the allow attributes directly, we can’t know which set of attributes to provide, because any browser in the world could potentially be loading that iframe.

Solutions?

Are the allow attributes on “parent” iframes really necessary?

Was this a regression? Or is this a feature? It sorta seems like the issue is that it’s possible for nested iframes to loosen permissions on a parent, which could be a security issue? It would be good to know where we fall here.

Could browsers just stop erroring or warning about unsupported allow attributes?

Looks like that’s what Safari is doing and that seems OK?

If this is the case, we could just ship the complete set of allow attributes to all browsers. A little verbose but prevents needing to user-agent sniff.

This could also help with the problem of needing to “keep up” with these attributes quite as much. For example, if Firefox starts to support the “rewriter” value, then it’ll just start working. This is better than some confused or disappointed user writing to support about it. Even being rather engaged with web platform news, we find it hard to catch when these very niche features evolve and need iframe attribute changes.

Could browsers give us API access to what allow attributes are supported?

Can the browser just tell us which ones it supports and then we could verify our list against that? Navigator.allow?

Also…

  • It’s not just the allow attribute. We also maintain browser-specific sets for the sandbox attribute. Right now, this isn’t affected by the nesting issues, but we could see it going that road.
  • This isn’t entirely about nested iframes. We use one level of iframe anywhere on codepen.io we show a preview of a Pen, and we need allow attributes there also. This is less of an immediate problem because of the user-agent sniffing JS we have access to do get them right, but ideally we wouldn’t have to do that at all.