biome suspicious/noPrototypeBuiltins: fix changes program behavior
Hypothesis Nemotron 3 Super predicted not to fire fired 1×
temporal dead zone after code is hoisted or reordered
Program
Output
TypeError Cannot read properties of undefined (reading 'hasOwnProperty')
TypeError Cannot convert undefined or null to object
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory intended-change · low
The rule rewrites foo.hasOwnProperty('x') to Object.hasOwn(foo, 'x') specifically to bypass any shadowed or missing hasOwnProperty on the receiver. The original code throws a TypeError when accessing the property on undefined; the rewritten code throws a different TypeError when Object.hasOwn receives undefined. Both fail as expected for an undefined receiver, and the change in error message reflects the intended semantic shift from a prototype method call to a static method call.
Explanation Nemotron 3 Super unverified
The original code checks `typeof foo === 'undefined'`; since `foo` is later defined as `{x:1}`, this condition is false, so the block is skipped—no error occurs. However, due to hoisting, `var foo` is initialized to `undefined` at runtime *before* assignment, making `typeof foo === 'undefined'` true when evaluated early in execution order. Inside the block, `foo.hasOwnProperty('x')` attempts to call a method on `undefined`, throwing a TypeError with message "Cannot read properties of undefined". The replacement uses `Object.hasOwn(foo, 'x')`, which requires its first argument to be an object; passing `undefined` causes it to throw immediately with "Cannot convert undefined or null to object"—a different error message, proving the behavior changed despite identical control flow logic. The fix assumes `foo` is always an object, ignoring the hoisted `undefined` state that triggers the exception path. This alters observable output, violating semantic equivalence.
Reproduce
- file
prog.js(the before program)- minimized program
- r1-p002.js
- evidence sheet
- r1-p002.md
- regression fixture
- r1-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 · Object.hasOwn replacement for prototype method · fix behavior change in typeof guard block
- related biomejs/biome/issues/10769 same noPrototypeBuiltins rule but different construct (computed member expression with __proto__) and different unsafe fix
- related biomejs/biome/issues/7900 same noPrototypeBuiltins rule mentioned in crash report but different defect (crash vs behavior change)
- related biomejs/biome/issues/281 same noPrototypeBuiltins rule mentioned in config but different defect (false positive on unused variables)
- related biomejs/biome/issues/4121 same noPrototypeBuiltins rule mentioned in config but different defect (line width for template literals)
Details
- program
- Temporal Dead Zone After Hoisting
- hazard
- temporal dead zone after code is hoisted or reordered
- oracle
stdout before: TypeError Cannot read properties of undefined (reading 'hasOwnProperty') stdout after: TypeError Cannot convert undefined or null to object- run
- 2026-10-17T21-09-20-346Z-6n46-biome-suspicious_noPrototypeBuiltins
generated program (8 lines) and the fix's diff
--- orig.js 2026-10-17 17:09:33.828976986 -0400 +++ fixed.js 2026-10-17 17:09:34.111979950 -0400 @@ -1,6 +1,6 @@ if (typeof foo === 'undefined') { try { - console.log(foo.hasOwnProperty('x')); + console.log(Object.hasOwn(foo, 'x')); } catch (e) { console.log(e.name, e.message); }
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");
```