oxc-project/oxc · warning · OxcDiagnostic

Require `for-in` loops to include an `if` statement

Error message

Require `for-in` loops to include an `if` statement

What it means

This is the `guard-for-in` lint rule (oxlint port of ESLint guard-for-in). It fires when a `for...in` loop's body is not wrapped in an `if` statement. The rationale is that for-in iterates inherited enumerable properties from the prototype chain, so unfiltered iteration can process unwanted keys; the rule is pedantic and off in ESLint's default sets.

Source

Thrown at crates/oxc_linter/src/rules/eslint/guard_for_in.rs:9

use oxc_ast::{AstKind, ast::Statement};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

use crate::{AstNode, context::LintContext, rule::Rule};

fn guard_for_in_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Require `for-in` loops to include an `if` statement")
        .with_help("The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype.")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct GuardForIn;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Require for-in loops to include an if statement.
    ///
    /// ### Why is this bad?
    ///
    /// Looping over objects with a `for in` loop will include properties that are inherited through
    /// the prototype chain. Using a `for in` loop without filtering the results in the loop can
    /// lead to unexpected items in your for loop which can then lead to unexpected behaviour.
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace the for-in with `for (const k of Object.keys(obj))` — this only iterates own enumerable keys and satisfies/obviates the rule.
  2. If keeping for-in, wrap the body in a guard such as `if (Object.prototype.hasOwnProperty.call(obj, k)) { ... }` or a domain filter `if (shouldProcess(k)) { ... }`.
  3. Disable the rule in `.oxlintrc.json` or with an inline `oxlint-disable guard-for-in` comment when the iterated object is known to be a null-prototype or trusted plain record.

Example fix

// before
for (const key in config) {
  apply(key, config[key]);
}

// after
for (const key of Object.keys(config)) {
  apply(key, config[key]);
}
Defensive patterns

Strategy: validation

Validate before calling

// Prefer Object.keys/entries so prototype keys can never leak in:
for (const [key, value] of Object.entries(config)) { /* ... */ }
// CI gate: oxlint --rule guard_for_in src/

Type guard

// If for-in must stay, make own-key iteration explicit:
if (Object.prototype.hasOwnProperty.call(obj, key)) { /* own property only */ }

Prevention

When it happens

Trigger: Any `for (const k in obj) { doSomething(k); }` whose direct body is not an `IfStatement`. The diagnostic is raised on every for-in statement the visitor finds where the loop body is not a single `if` (crates/oxc_linter/src/rules/eslint/guard_for_in.rs). There are no configuration options.

Common situations: Enabling pedantic/strict rule presets (e.g. migrating a config with `guard-for-in: error` to oxlint); legacy code that iterates plain objects with for-in; newly added for-in loops in a repo where the rule was already on; iterating over objects that have been extended or use prototypes/class instances.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/5740bb02964d78bc. Report an issue: GitHub.