fixhunt

biome suspicious/noPrototypeBuiltins: fix changes program behavior

fix-changes-behaviorlabelled safeintended-change · lowrelated
Findings / 2026-10-17T21-09-20-346Z-6n46-biome-suspicious_noPrototypeBuiltins / r2-p002biome 2.5.1510 → 8 lines2026-10-17 21:09 UTC

Hypothesis Nemotron 3 Super predicted to fire fired 1×

getters, setters and Object.defineProperty side effects

Program

before
1const obj = {};
2Object.defineProperty(obj, 'hasOwnProperty', {
3 get() {
4 console.log('Getter called');
5 return Object.prototype.hasOwnProperty;
6 }
7});
8obj.hasOwnProperty('x');
after
1const obj = {};
2Object.defineProperty(obj, 'hasOwnProperty', {
3 get() {
4 console.log('Getter called');
5 return Object.prototype.hasOwnProperty;
6 }
7});
8Object.hasOwn(obj, 'x');

Output

stdout beforeexit 0
Getter called
stdout afterexit 0
(no stdout)
fired
1 before · 0 after
runs
each version twice, same file name, no network

Judge Nemotron 3 Ultra advisory intended-change · low

The rule explicitly warns that prototype methods like hasOwnProperty can be shadowed and replaces direct calls with Object.hasOwn to bypass the object's own property. The program demonstrates this exact scenario by defining a custom hasOwnProperty getter; the fix intentionally changes behavior to call the safe built-in instead of the shadowed getter.

Explanation Nemotron 3 Super unverified

The original call `obj.hasOwnProperty('x')` invokes the custom getter defined on `obj`, which logs "Getter called" before returning the function from `Object.prototype.hasOwnProperty`. The replacement `Object.hasOwn(obj, 'x')` bypasses any property named `hasOwnProperty` on `obj` entirely, directly using the built-in static method that does not trigger the getter. Thus, the side effect of logging is omitted, changing observable behavior. This violates semantic equivalence because the fix assumes `hasOwnProperty` refers to the inherited method, but the program intentionally overrides it via a getter. The transformation is unsafe when the property is shadowed with non-standard behavior.

Reproduce

file
prog.js (the before program)
minimized program
r2-p002.js
evidence sheet
r2-p002.md
regression fixture
r2-p002.js the minimized program with a header stating the observed change, for the tool's test suite
node prog.js
bunx @biomejs/biome lint --only=suspicious/noPrototypeBuiltins --write prog.js
node prog.js

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

noPrototypeBuiltins fix · suspicious noPrototypeBuiltins hasOwnProperty call · biome lint rule suspicious noPrototypeBuiltins override · Object.defineProperty redefines hasOwnProperty getter

  • related biomejs/biome/issues/10769 useLiteralKeys rule flags __proto__ in computed member expression, same rule family (prototype builtins) but different construct

Details

program
Getter Side Effect via DefineProperty
hazard
getters, setters and Object.defineProperty side effects
oracle
stdout before: Getter called stdout after:
run
2026-10-17T21-09-20-346Z-6n46-biome-suspicious_noPrototypeBuiltins
generated program (10 lines) and the fix's diff
1const obj = {};
2Object.defineProperty(obj, 'hasOwnProperty', {
3 get() {
4 console.log('Getter called');
5 return Object.prototype.hasOwnProperty;
6 }
7});
8console.log('Before:');
9obj.hasOwnProperty('x');
10console.log('After:');
--- orig.js	2026-10-17 17:09:45.699101165 -0400
+++ fixed.js	2026-10-17 17:09:45.977104070 -0400
@@ -6,5 +6,5 @@
   }
 });
 console.log('Before:');
-obj.hasOwnProperty('x');
+Object.hasOwn(obj, 'x');
 console.log('After:');
rule documentation given to the models
Summary

- Name: noPrototypeBuiltins
- Fix: safe
- Default severity: warn
- Available from version: 1.1.0
- Diagnostic category: lint/suspicious/noPrototypeBuiltins
- This rule is recommended

Description

 Disallow direct use of `Object.prototype` builtins.

 ECMAScript 5.1 added `Object.create` which allows the creation of an object with a custom prototype.
 This pattern is often used for objects used as Maps. However, this pattern can lead to errors
 if something else relies on prototype properties/methods.
 Moreover, the methods could be shadowed, this can lead to random bugs and denial of service
 vulnerabilities. For example, calling `hasOwnProperty` directly on parsed JSON like `{"hasOwnProperty": 1}` could lead to vulnerabilities.
 To avoid subtle bugs like this, you should call these methods from `Object.prototype`.
 For example, `foo.isPrototypeOf(bar)` should be replaced with `Object.prototype.isPrototypeOf.call(foo, "bar")`
 As for the `hasOwn` method, `foo.hasOwn("bar")` should be replaced with `Object.hasOwn(foo, "bar")`.

Examples

Invalid

 ```js,expect_diagnostic
 var invalid = foo.hasOwnProperty("bar");
 ```

 ```js,expect_diagnostic
 var invalid = foo.isPrototypeOf(bar);
 ```

 ```js,expect_diagnostic
 var invalid = foo.propertyIsEnumerable("bar");
 ```

 ```js,expect_diagnostic
 Object.hasOwnProperty.call(foo, "bar");
 ```

Valid

 ```js
 var valid = Object.hasOwn(foo, "bar");
 var valid = Object.prototype.isPrototypeOf.call(foo, bar);
 var valid = {}.propertyIsEnumerable.call(foo, "bar");
 ```