Unguarded for…in
ID |
javascript.guard_for_in |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
best-practice, reliability |
Description
Reports for … in loops whose body does not start with an if that filters by Object.prototype.hasOwnProperty (or one of its safer shapes). A bare for…in iterates over every enumerable property of the object — including those inherited from the prototype chain.
Rationale
for…in walks the prototype chain. Without an own-property guard:
-
properties added to
Object.prototype(or any ancestor) by other code leak into the loop body, -
the loop is sensitive to the iteration order of inherited properties, which is implementation-defined,
-
the bug is invisible until a library or polyfill modifies a shared prototype.
// Bad - iterates inherited keys too
for (const key in user) {
process(user[key]);
}
Remediation
Use one of the standard guards, or switch to Object.keys(…) / Object.entries(…) which already skip inherited properties.
// Good - explicit guard
for (const key in user) {
if (Object.hasOwn(user, key)) {
process(user[key]);
}
}
// Good - use Object.keys instead
for (const key of Object.keys(user)) {
process(user[key]);
}