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 served from a non-same-origin URL. 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.
Say 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. Since the JavaScript in the iframe is not same-origin, it is subject to permissions policies.
Without the allow
attribute on our <iframe>
it would throw an error when the user tries to execute that JavaScript.
Failed to copy: NotAllowedError: Failed to execute 'writeText' on 'Clipboard': The Clipboard API has been blocked because of a permissions policy applied to the current document. See https://crbug.com/414348233 for more details.
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’s Embedded Pens have a nested <iframe>
structure like this:
The code essentially looks like this, illustrated with the iframe page content inline.
<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>
To support the JavaScript APIs, we need to put the allow
attribute on the Preview iframe 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>
Uh-oh! Now we have a problem.
Recently (Chrome 136+) this error gets thrown as soon as the nested iframe has the allow attribute:
[Violation] Potential permissions policy violation: clipboard-write is not allowed in this document.
With our complete list (which I’ll include below), these error logs are very intense and noisy:

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.
Every browser has a different set of allow
attribute values that it 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 control.
The list of allow
values for Google Chrome
We need all of these values in the allow
attribute for users to test safe browser APIs. We constantly adjust to add 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 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:

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:
Unrecognized feature: 'fartsandwich'.
Those AI-related attributes require a trial which also throw warnings, so most users get that noise as well.

We Need To Do User-Agent Sniffing (sorry!)
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. We’ve also been around long enough that you gotta do what you gotta do to solve problems. While we don’t love it, we’ve been doing this for many years and it’s mostly worked.
Can’t Sniff Without ‘Script.
Unfortunately the user-agent sniffing is limited to where a script can run on the parent page which has the <iframe>
:
<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, so there’s no script that runs on the parent page.
- 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) - oEmbed API. A server-side call returns an
<iframe>
to be embedded.
The nested structure of our embeds has helped us here where that first level of iframe can attempt to user-agent sniff and apply the correct allow
attributes to the internal Preview 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 CodePen 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
?
We’d likely still need our own list of the safe attributes we want to support, and this would still limit the implementation to where a script can run on the parent page, but an API could provide better insight than a hardcoded browser list.
Also…
- It’s not just the
allow
attribute. We also maintain browser-specific sets for thesandbox
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 needallow
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.