Skip to content

feat: implement useIframeSandbox#9949

Merged
Netail merged 8 commits intobiomejs:mainfrom
Netail:feat/use-iframe-sandbox
Apr 14, 2026
Merged

feat: implement useIframeSandbox#9949
Netail merged 8 commits intobiomejs:mainfrom
Netail:feat/use-iframe-sandbox

Conversation

@Netail
Copy link
Copy Markdown
Member

@Netail Netail commented Apr 12, 2026

Summary

Port https://www.eslint-react.xyz/docs/rules/dom-no-missing-iframe-sandbox, which enforces setting the sandbox attribute on iframe tags

Test Plan

Unit tests

Docs

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 12, 2026

🦋 Changeset detected

Latest commit: d390106

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Netail Netail marked this pull request as draft April 12, 2026 21:12
@github-actions github-actions bot added A-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages A-Diagnostic Area: diagnostocis L-HTML Language: HTML and super languages labels Apr 12, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Added a nursery lint rule useIframeSandbox for HTML and JSX that detects iframe elements using source-type-aware name matching and signals when sandbox is missing or its value is indeterminate. Implemented diagnostics (warning + two notes), new empty rule-options type and export, test fixtures (valid/invalid) for HTML and JSX, an HTML iframe-detection adjustment to use RuleContext/HtmlFileSource, and a changeset for a patch release.

Possibly related PRs

Suggested reviewers

  • dyc3
  • ematipico
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: implement useIframeSandbox' directly and clearly describes the main change: implementing a new linter rule for enforcing sandbox attributes on iframe elements across both HTML and JSX contexts.
Description check ✅ Passed The description is related to the changeset, clearly explaining the purpose of porting an ESLint rule to enforce sandbox attributes on iframe tags, and noting unit tests as the test plan.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_html_analyze/src/lint/nursery/use_iframe_sandbox.rs`:
- Around line 52-55: The diagnostic currently only triggers when a sandbox
attribute exists but has no value; update the logic in use_iframe_sandbox (where
is_iframe_element(...) and element.find_attribute_by_name("sandbox") are used)
to also handle the missing-sandbox case: treat
element.find_attribute_by_name("sandbox") returning None as a failing case and
emit the same diagnostic for <iframe></iframe> as for sandbox="" (i.e., if no
sandbox attribute OR sandbox_attribute.value().is_none(), create the
diagnostic). Ensure you adjust the conditional and any references to
sandbox_attribute accordingly so both missing and empty sandbox attributes are
reported.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 65e63434-84e1-44c6-9502-84c9864aebec

📥 Commits

Reviewing files that changed from the base of the PR and between 9956f1d and 98014a3.

⛔ Files ignored due to path filters (7)
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/linter_options_check.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/valid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/invalid.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/valid.jsx.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (9)
  • .changeset/fluffy-ways-punch.md
  • crates/biome_html_analyze/src/lint/nursery/use_iframe_sandbox.rs
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/invalid.html
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/valid.html
  • crates/biome_js_analyze/src/lint/nursery/use_iframe_sandbox.rs
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/invalid.jsx
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/valid.jsx
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/use_iframe_sandbox.rs

Comment thread crates/biome_html_analyze/src/lint/nursery/use_iframe_sandbox.rs Outdated
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 12, 2026

Merging this PR will not alter performance

✅ 126 untouched benchmarks
⏩ 128 skipped benchmarks1


Comparing Netail:feat/use-iframe-sandbox (d390106) with main (f8d49d9)2

Open in CodSpeed

Footnotes

  1. 128 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (322675e) during the generation of this report, so f8d49d9 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@github-actions github-actions bot added the A-CLI Area: CLI label Apr 12, 2026
dyc3
dyc3 previously requested changes Apr 12, 2026
language: "html",
recommended: false,
severity: Severity::Warning,
sources: &[RuleSource::EslintReactDom("no-missing-iframe-sandbox").same(), RuleSource::EslintReactXyz("dom-no-missing-iframe-sandbox").same()],
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.

kinda unrelated, but do you think we could have a unit test or something to flag rules that don't have the correct rule sources? specifically for this EslintReactXyz plugin.

basically, we should be able to flag in a unit test or something:

  • rule has a EslintReactXyz source, but no corresponding "sub-source" like EslintReactDom (if applicable)
  • vice versa, rule has the "sub-source" like EslintReactDom, but no corresponding EslintReactXyz (always applicable)

The reason I'm asking is because things that aren't enforced automatically degrade over time. Something to think about for another PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Was thinking about that, if we can somehow lint that, could you point me into the right direction on where this kind of linting happens?

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.

I haven't looked at it too closely yet so not precisely. But we would make these assertions through unit tests, not via linting. Similar to how we have a bunch of unit tests that assert certain lists are sorted so binary searches work.

We would probably place these unit tests in the biome_js_analyze crate. Probably the biome_analyze::RegistryVisitor trait would be involved to iterate over rules? Again, not sure, haven't looked at it closely, but maybe that could help you look into it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Alright, will check that out in another PR

rule_category!(),
node.range(),
markup! {
"Provide a "<Emphasis>"sandbox"</Emphasis>" attribute when using "<Emphasis>"iframe"</Emphasis>" elements."
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.

Rule pillars. this message conflates the "what" with the "how to fix"

first message needs to describe what the error is. In this case, something like "this iframe is missing sandbox"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yup, wasn't really happy about it either. Hence the draft 😅

/// - In component-based frameworks, only lowercase `iframe` is matched to avoid flagging custom components like `<Iframe>`.
fn is_iframe_element(element: &AnyHtmlElement, file_extension: &str) -> bool {
element.name().is_some_and(|token_text| {
let is_html_file = file_extension == "html";
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.

you should be using the HtmlFileSource to determine this

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ahh okay, built this off of useIframeTitle

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.

oh, well that sucks, we should probably fix that.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Tackled that one too, will extract that function into a more abstract way to also be used by other tags

@Netail Netail force-pushed the feat/use-iframe-sandbox branch from b187ba7 to ff31004 Compare April 13, 2026 19:27
@Netail Netail marked this pull request as ready for review April 13, 2026 19:27
Comment on lines +90 to 105
fn is_iframe_element(element: &AnyHtmlElement, ctx: &RuleContext<UseIframeTitle>) -> bool {
let Some(element_name) = element.name() else {
return false;
};

let source_type = ctx.source_type::<HtmlFileSource>();

// In HTML files: case-insensitive (IFRAME, Iframe, iframe all match)
// In component frameworks (Vue, Svelte, Astro): case-sensitive (only "iframe" matches)
// This means <Iframe> in Vue/Svelte is treated as a component and ignored
if source_type.is_html() {
element_name.text().eq_ignore_ascii_case("iframe")
} else {
element_name.text() == "iframe"
}
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Will extract this function in a different PR, because it saw more components that could use this. But it will be a bit much for this PR

Comment on lines +85 to +100
fn is_iframe_element(element: &AnyHtmlElement, ctx: &RuleContext<UseIframeSandbox>) -> bool {
let Some(element_name) = element.name() else {
return false;
};

let source_type = ctx.source_type::<HtmlFileSource>();

// In HTML files: case-insensitive (IFRAME, Iframe, iframe all match)
// In component frameworks (Vue, Svelte, Astro): case-sensitive (only "iframe" matches)
// This means <Iframe> in Vue/Svelte is treated as a component and ignored
if source_type.is_html() {
element_name.text().eq_ignore_ascii_case("iframe")
} else {
element_name.text() == "iframe"
}
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Same

@Netail Netail requested a review from dyc3 April 13, 2026 19:29
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/invalid.html`:
- Line 3: The rule implementation for dom-no-missing-iframe-sandbox is
incorrectly rejecting a bare sandbox attribute because it treats attributes with
value().is_none() as missing; update the rule check to treat a bare sandbox
(attribute present with no value) as equivalent to sandbox="" (i.e., accept when
the attribute exists even if value().is_none()), or alternatively change the
rule metadata/source to document/enforce stricter semantics—modify the condition
that currently rejects attributes with value().is_none() so that presence of the
sandbox attribute passes validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b3975744-915c-4e44-9452-771e58b60359

📥 Commits

Reviewing files that changed from the base of the PR and between 98014a3 and ff31004.

⛔ Files ignored due to path filters (10)
  • crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs is excluded by !**/migrate/eslint_any_rule_to_biome.rs and included by **
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/linter_options_check.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/valid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/invalid.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/valid.jsx.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (10)
  • .changeset/fluffy-ways-punch.md
  • crates/biome_html_analyze/src/lint/a11y/use_iframe_title.rs
  • crates/biome_html_analyze/src/lint/nursery/use_iframe_sandbox.rs
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/invalid.html
  • crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/valid.html
  • crates/biome_js_analyze/src/lint/nursery/use_iframe_sandbox.rs
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/invalid.jsx
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/valid.jsx
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/use_iframe_sandbox.rs
✅ Files skipped from review due to trivial changes (5)
  • .changeset/fluffy-ways-punch.md
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/invalid.jsx
  • crates/biome_js_analyze/tests/specs/nursery/useIframeSandbox/valid.jsx
  • crates/biome_rule_options/src/use_iframe_sandbox.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/biome_js_analyze/src/lint/nursery/use_iframe_sandbox.rs
  • crates/biome_html_analyze/src/lint/nursery/use_iframe_sandbox.rs

Comment thread crates/biome_html_analyze/tests/specs/nursery/useIframeSandbox/invalid.html Outdated
Comment thread crates/biome_html_analyze/src/lint/nursery/use_iframe_sandbox.rs Outdated
Comment thread crates/biome_js_analyze/src/lint/nursery/use_iframe_sandbox.rs Outdated
@Netail Netail force-pushed the feat/use-iframe-sandbox branch from 1b7b095 to 4af974e Compare April 13, 2026 20:34
@Netail Netail force-pushed the feat/use-iframe-sandbox branch from 4af974e to c056dad Compare April 13, 2026 20:45
@Netail Netail requested a review from ematipico April 13, 2026 21:15
Comment thread .changeset/fluffy-ways-punch.md Outdated
Comment thread .changeset/fluffy-ways-punch.md Outdated
Comment thread .changeset/fluffy-ways-punch.md Outdated
@Netail Netail dismissed dyc3’s stale review April 14, 2026 14:02

Addressed

@Netail Netail merged commit e0ba71d into biomejs:main Apr 14, 2026
33 checks passed
@Netail Netail deleted the feat/use-iframe-sandbox branch April 14, 2026 14:02
@github-actions github-actions bot mentioned this pull request Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI A-Diagnostic Area: diagnostocis A-Linter Area: linter A-Project Area: project L-HTML Language: HTML and super languages L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants