{"record":{"id":"5740bb02964d78bc","repo":"oxc-project/oxc","slug":"require-for-in-loops-to-include-an-if-statemen","errorCode":null,"errorMessage":"Require `for-in` loops to include an `if` statement","messagePattern":"Require `for-in` loops to include an `if` statement","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/guard_for_in.rs","lineNumber":9,"sourceCode":"use oxc_ast::{AstKind, ast::Statement};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{AstNode, context::LintContext, rule::Rule};\n\nfn guard_for_in_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Require `for-in` loops to include an `if` statement\")\n        .with_help(\"The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct GuardForIn;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Require for-in loops to include an if statement.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// Looping over objects with a `for in` loop will include properties that are inherited through\n    /// the prototype chain. Using a `for in` loop without filtering the results in the loop can\n    /// lead to unexpected items in your for loop which can then lead to unexpected behaviour.\n    ///","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/guard_for_in.rs#L1-L27","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Replace the for-in with `for (const k of Object.keys(obj))` — this only iterates own enumerable keys and satisfies/obviates the rule.","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)) { ... }`.","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."],"exampleFix":"// before\nfor (const key in config) {\n  apply(key, config[key]);\n}\n\n// after\nfor (const key of Object.keys(config)) {\n  apply(key, config[key]);\n}","handlingStrategy":"validation","validationCode":"// Prefer Object.keys/entries so prototype keys can never leak in:\nfor (const [key, value] of Object.entries(config)) { /* ... */ }\n// CI gate: oxlint --rule guard_for_in src/","typeGuard":"// If for-in must stay, make own-key iteration explicit:\nif (Object.prototype.hasOwnProperty.call(obj, key)) { /* own property only */ }","tryCatchPattern":null,"preventionTips":["Default to Object.keys/values/entries for plain-object iteration; reserve for-in for cases where prototype traversal is intended.","Treat any new for-in in review as a question: which properties do you expect, including inherited ones?","Freeze or create objects with Object.create(null) when they are used as dictionaries, removing prototype hazards entirely."],"tags":["eslint","oxlint","correctness","for-in","prototype-chain","pedantic"],"backgroundTag":"for-in-prototype-iteration","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}