Skip to content

Add sandbox attribute to extension iframe in DevTools. - #9967

Open
johnpryan wants to merge 9 commits into
flutter:masterfrom
johnpryan:iframe-security
Open

Add sandbox attribute to extension iframe in DevTools.#9967
johnpryan wants to merge 9 commits into
flutter:masterfrom
johnpryan:iframe-security

Conversation

@johnpryan

Copy link
Copy Markdown
Contributor

This change grants these permissions:

  • allow-scripts: enables extension JS / Wasm execution.
  • allow-forms: permits standard form interactions.
  • allow-downloads: allows extensions to export files/logs.
  • allow-popups & allow-popups-to-escape-sandbox: allows opening external links.

This does not grant allow-same-origin permission, so extensions can't access the parent window's DOM, cookies, or local storage.

This change grants these permissions:
- `allow-scripts`: enables extension JS / Wasm execution.
- `allow-forms`: permits standard form interactions.
- `allow-downloads`: allows extensions to export files/logs.
- `allow-popups` & `allow-popups-to-escape-sandbox`: allows opening
   external links.

This does not grant `allow-same-origin` permission, so extensions can't
access the parent window's DOM, cookies, or local storage.
@johnpryan
johnpryan marked this pull request as ready for review August 18, 2026 20:07
@johnpryan
johnpryan requested a review from a team as a code owner August 18, 2026 20:07
@johnpryan
johnpryan requested review from bkonyi and removed request for a team August 18, 2026 20:07

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces iframe sandboxing for embedded DevTools extensions to enforce origin isolation, and updates the release notes. The reviewer recommended extracting the raw sandbox configuration string into a descriptive named constant to avoid magic strings, in accordance with the repository style guide.

Comment thread packages/devtools_app/lib/src/extensions/embedded/_controller_web.dart Outdated
@srawlins

Copy link
Copy Markdown
Contributor

Does this fix a specific issue that's been opened?

@johnpryan

Copy link
Copy Markdown
Contributor Author

See b/535724008

@kenzieschmoll kenzieschmoll left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How was this tested? The iFrame does need to talk back and forth with the parent for the DevTools extension API, so just want to make sure everything here still works.

@johnpryan

Copy link
Copy Markdown
Contributor Author

This should still allow postMessage communication with DevTools, but I only tested this with the foo_ext mock package, I will test this with a real-world package and let you know if anything stops working.

Flutter Web extensions require same-origin access for flutter.js to
initialize Service Workers and web storage without throwing a
SecurityError.

This is still secure because the extension must be enabled, and
the sandbox prevents top-level navigation, popups, and modal hijacking.
@johnpryan

Copy link
Copy Markdown
Contributor Author

I ran a more complete test on the patrol package example and found that we needed to add the allow-same-origin header also.

These headers still prevent extensions from page-hijacking, displaying popups, etc, so this is still a good thing to do.

@johnpryan

Copy link
Copy Markdown
Contributor Author

Need to verify that the extension reload feature still works.

@johnpryan

Copy link
Copy Markdown
Contributor Author

@kenzieschmoll I verified that the "Force reload" button still reloads the extension. This is ready for another look.

Comment thread .agents/skills/debugging-devtools-extensions/SKILL.md Outdated
Comment on lines +62 to +75
<p id="reload-info"></p>
<script>
document.getElementById('reload-info').textContent = 'Rendered at ' + new Date().toLocaleTimeString() + ' (Token: ' + Math.random().toString(36).substring(2, 8) + ')';

window.addEventListener('message', (event) => {
const data = event.data;
if (!data) return;
if (data.type === 'ping') {
window.parent.postMessage({ type: 'pong' }, '*');
} else if (data.type === 'forceReload') {
window.location.reload();
}
});
</script>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this in the placeholder? There is already a button on the container that surrounds the extension to reload the iFrame

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was using it to test the reload feature, I can remove it if you want.

/// The sandbox permissions granted to embedded extension iframes.
///
/// Grants the extension same-origin capabilities (needed for service workers,
/// storage, etc.) while allowing javascript execution, forms, downloads, and

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be "and" instead of "while"? while makes it sound like a contradiction.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read this as "Prevents X while allowing Y", seems fine to me?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

64b7d88 should make this more clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants