biome suspicious/noPrototypeBuiltins: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
The fix removes any opportunity for side effects in the retrieval of foo.hasOwnProperty—such as logging in a get trap or modifying state—because it no longer accesses the property on foo at all, where
Program
Output
Trap hit for hasOwnProperty, access # 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 rewrites direct calls like obj.hasOwnProperty('foo') to Object.hasOwn(obj, 'foo') to bypass any shadowed or custom hasOwnProperty on the object. The program demonstrates this by using a Proxy that traps access to hasOwnProperty; the fix intentionally avoids that trap, changing the observable behavior exactly as the documentation describes.
Explanation Nemotron 3 Super unverified
The original call `obj.hasOwnProperty('foo')` invokes the proxy’s `get` trap because property lookup on `obj` triggers it; when `prop` equals `'hasOwnProperty'`, the trap logs before returning the inherited method. The replacement `Object.hasOwn(obj, 'foo')` is a direct function call that does not access any property on `obj`, so the proxy’s `get` trap is never invoked and no logging occurs. Thus the rewrite changes observable behavior.
Reproduce
- file
prog.js(the before program)- minimized program
- r2-p005.js
- evidence sheet
- r2-p005.md
- regression fixture
- r2-p005.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 proxy trap · Proxy object hasOwnProperty call · handler get method interception
- related biomejs/biome/issues/10769 useLiteralKeys flags __proto__ in computed member expression, same rule family (noPrototypeBuiltins) but different construct (computed member vs direct property access)
Details
- program
- Property Access Trap Side Effect Lost
- hazard
- The fix removes any opportunity for side effects in the retrieval of foo.hasOwnProperty—such as logging in a get trap or modifying state—because it no longer accesses the property on foo at all, where
- oracle
stdout before: Trap hit for hasOwnProperty, access # 0 stdout after:- run
- 2026-10-17T21-09-20-346Z-6n46-biome-suspicious_noPrototypeBuiltins
generated program (20 lines) and the fix's diff
--- orig.js 2026-10-17 17:09:47.033115103 -0400 +++ fixed.js 2026-10-17 17:09:47.306117955 -0400 @@ -12,9 +12,9 @@ const obj = new Proxy({ foo: 1 }, handler); accessCount = 0; console.log('Before (original):'); -obj.hasOwnProperty('foo'); +Object.hasOwn(obj, 'foo'); console.log('Access count after original:', accessCount); accessCount = 0; console.log('\nAfter (fixed):'); -Object.prototype.hasOwnProperty.call(obj, 'foo'); +Object.hasOwn(obj, 'foo'); console.log('Access count after fixed:', accessCount);
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");
```