fixhunt

biome suspicious/noPrototypeBuiltins

labelled safe
Runs / 2026-10-17T21-09-20-346Z-6n46-biome-suspicious_noPrototypeBuiltinsbiome 2.5.152026-10-17 21:09 UTC8 programs × 2 round(s)16 programs, 16 fired, 16 fixed, 7 findings, 0 rejectedmodel cost $0.11

Analysis Nemotron 3 Super

Flags direct calls to Object.prototype methods (hasOwnProperty, isPrototypeOf, propertyIsEnumerable) invoked on arbitrary objects.

Fix: Replaces obj.methodName(args) with Object.prototype.methodName.call(obj, args) for hasOwnProperty, isPrototypeOf, and propertyIsEnumerable; replaces obj.hasOwnProperty with Object.hasOwn when applicable per rule documentation.

11 hazards
  • Rewriting foo.hasOwnProperty("bar") to Object.prototype.hasOwnProperty.call(foo, "bar") changes behavior if foo is null or undefined, as the former throws a TypeError while the latter also throws but may be caught differently due to call stack differences.
  • If foo.hasOwnProperty is a non-function value (e.g., a number or string), the original code throws TypeError when invoked, but the fix attempts to call Object.prototype.hasOwnProperty.call which expects a function, preserving the error but altering the error path.
  • When foo is declared with let or const and used before initialization in the same block, the fix does not alter the TDZ error timing, but if the original relied on foo being accessible via a scope hole, the fix does not change that—however, no behavioral shift occurs here as both forms reference foo identically.
  • If foo is a proxy with a get trap that returns a non-function for hasOwnProperty, the original invokes the trap and then attempts to call the result, throwing TypeError; the fix bypasses the trap entirely by referencing Object.prototype directly, so the get trap is not triggered, altering observable behavior.
  • In strict mode, if foo.hasOwnProperty is accessed via a with statement (deprecated but possible), the original resolves foo in the with scope, while the fix references Object.prototype globally, potentially changing the base object if the with scope had an Object property.
  • 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, whereas the original evaluates foo.hasOwnProperty as an expression before calling it.
  • If the code depends on the call stack showing foo.hasOwnProperty in traces (e.g., for debugging or error reporting), replacing it with Object.prototype.hasOwnProperty.call alters the stack trace, which could affect error handling logic that inspects stack frames.
  • When the argument "bar" is an expression with side effects (e.g., a function call), the evaluation order of arguments is preserved in the fix, but if the original relied on the this-value being evaluated after arguments (which it never is in JS), no change occurs—however, this is not a real hazard since this-binding always happens before argument evaluation in calls.
  • If foo is document.all in legacy browsers (which acts like undefined for == null but has special behavior), the original may behave inconsistently due to its [[Call]] semantics, while the fix uses standard Function.prototype.call, potentially altering behavior in edge cases involving IE-specific quirks.
  • If the code is parsed in a context where Object.prototype has been overridden (e.g., via iframe pollution or deliberate mutation), the fix uses the current Object.prototype, which may differ from the original object's actual prototype chain if inheritance was altered, though this affects both original and fix similarly since both rely on Object.prototype.
  • Comments attached to the original call site (e.g., foo.hasOwnProperty/*note*/("bar")) may be lost or misplaced during the rewrite if the autofix does not preserve trailing or inline comments, degrading code readability.

Findings

programoraclelabeljudgestatussummary
r1-p007fix-changes-behaviorlabelled safeintended-change · highrelatedThe program deliberately shadows hasOwnProperty on obj with a non-function value (42). The rule exists precisely to bypass such shadowing by rewriting obj.hasO…
r2-p007fix-changes-behaviorlabelled safeintended-change · highrelatedThe rule explicitly rewrites direct calls like obj.hasOwnProperty('x') to Object.hasOwn(obj, 'x') to bypass shadowed or missing prototype methods. The program …
r1-p002fix-changes-behaviorlabelled safeintended-change · lowrelatedThe rule rewrites foo.hasOwnProperty('x') to Object.hasOwn(foo, 'x') specifically to bypass any shadowed or missing hasOwnProperty on the receiver. The origina…
r1-p006fix-changes-behaviorlabelled safeintended-change · lowrelatedThe rule rewrites `fakeAll.hasOwnProperty('length')` to `Object.hasOwn(fakeAll, 'length')` to bypass any shadowed `hasOwnProperty` method. The program delibera…
r2-p001fix-changes-behaviorlabelled safeintended-change · lowrelatedThe rule intentionally replaces direct prototype method calls with static Object.hasOwn to avoid shadowing vulnerabilities. The original code threw a TypeError…
r2-p002fix-changes-behaviorlabelled safeintended-change · lowrelatedThe rule explicitly warns that prototype methods like hasOwnProperty can be shadowed and replaces direct calls with Object.hasOwn to bypass the object's own pr…
r2-p005fix-changes-behaviorlabelled safeintended-change · lowrelatedThe rule explicitly rewrites direct calls like obj.hasOwnProperty('foo') to Object.hasOwn(obj, 'foo') to bypass any shadowed or custom hasOwnProperty on the ob…

Programs

idresulttitlehazard
r1-p001fix okOrder of Evaluation - Side Effects Duplicatedorder of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never)
r1-p002fix-changes-behavior prediction offTemporal Dead Zone After Hoistingtemporal dead zone after code is hoisted or reordered
r1-p003fix okTDZ Error Timing Unchanged by FixWhen foo is declared with let or const and used before initialization in the same block, the fix does not alter the TDZ error timing...
r1-p004fix okNumeric/String Coercionnumeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt
r1-p005fix ok__proto__ Keys and Prototype Access__proto__ keys, prototype access, Object.assign vs spread
r1-p006fix-changes-behaviordocument.all Legacy QuirkIf foo is document.all in legacy browsers [...] potentially altering behavior in edge cases involving IE-specific quirks.
r1-p007fix-changes-behaviorNon-Function hasOwnProperty ValueIf foo.hasOwnProperty is a non-function value (e.g., a number or string), the original code throws TypeError when invoked, but the fix attempts to call Object.prototype.hasOwnProperty.call which expec
r1-p008fix okthis Binding: Arrow vs Functionthis binding: arrow vs function, methods extracted from objects, call/apply/bind
r2-p001fix-changes-behaviorNull/undefined Distinction with Optional Chainingnull/undefined distinction, optional chaining short-circuit, nullish vs falsy
r2-p002fix-changes-behaviorGetter Side Effect via DefinePropertygetters, setters and Object.defineProperty side effects
r2-p003fix okAsync Await Interaction with Property Accessasync/await ordering, generators and yield position
r2-p004fix okOrder of Evaluation - Side Effects Doubledorder of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never)
r2-p005fix-changes-behaviorProperty Access Trap Side Effect LostThe 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
r2-p006fix okArgument Evaluation Order PreservedWhen the argument "bar" is an expression with side effects (e.g., a function call), the evaluation order of arguments is preserved in the fix, but if the original relied on the this-value being evalua
r2-p007fix-changes-behaviorNon-function hasOwnProperty ValueIf foo.hasOwnProperty is a non-function value (e.g., a number or string), the original code throws TypeError when invoked, but the fix attempts to call Object.prototype.hasOwnProperty.call which expec
r2-p008fix okthis Binding: Arrow vs Function Method Extractionthis binding: arrow vs function, methods extracted from objects, call/apply/bind

Sources

r1-p001 · Order of Evaluation - Side Effects Duplicated
1let counter = 0;
2function getKey() {
3 return ++counter;
4}
5const obj = {};
6try {
7 console.log(obj[getKey()] = 'first', obj.hasOwnProperty(getKey()));
8} catch (e) {
9 console.log(e.name, e.message);
10}
--- orig.js	2026-10-17 17:09:33.367972158 -0400
+++ fixed.js	2026-10-17 17:09:33.654975164 -0400
@@ -4,7 +4,7 @@
 }
 const obj = {};
 try {
-  console.log(obj[getKey()] = 'first', obj.hasOwnProperty(getKey()));
+  console.log(obj[getKey()] = 'first', Object.hasOwn(obj, getKey()));
 } catch (e) {
   console.log(e.name, e.message);
 }
first false
r1-p002 · Temporal Dead Zone After Hoisting
1if (typeof foo === 'undefined') {
2 try {
3 console.log(foo.hasOwnProperty('x'));
4 } catch (e) {
5 console.log(e.name, e.message);
6 }
7}
8var foo = { x: 1 };
--- 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);
   }
TypeError Cannot read properties of undefined (reading 'hasOwnProperty')
r1-p003 · TDZ Error Timing Unchanged by Fix
1{
2 try {
3 console.log(value.hasOwnProperty('a'));
4 } catch (e) {
5 console.log(e.name, e.message);
6 }
7 const value = {};
8}
--- orig.js	2026-10-17 17:09:34.282981741 -0400
+++ fixed.js	2026-10-17 17:09:34.565984705 -0400
@@ -1,6 +1,6 @@
 { 
   try {
-    console.log(value.hasOwnProperty('a'));
+    console.log(Object.hasOwn(value, 'a'));
   } catch (e) {
     console.log(e.name, e.message);
   }
ReferenceError Cannot access 'value' before initialization
r1-p004 · Numeric/String Coercion
1const obj = {
2 [Symbol.toPrimitive](hint) { return hint === 'string' ? 'prop' : 42; }
3};
4console.log(obj.hasOwnProperty('prop'), obj.hasOwnProperty(42));
5console.log(Object.prototype.hasOwnProperty.call(obj, 'prop'), Object.prototype.hasOwnProperty.call(obj, 42));
--- orig.js	2026-10-17 17:09:34.738986516 -0400
+++ fixed.js	2026-10-17 17:09:35.001989271 -0400
@@ -1,5 +1,5 @@
 const obj = {
   [Symbol.toPrimitive](hint) { return hint === 'string' ? 'prop' : 42; }
 };
-console.log(obj.hasOwnProperty('prop'), obj.hasOwnProperty(42));
-console.log(Object.prototype.hasOwnProperty.call(obj, 'prop'), Object.prototype.hasOwnProperty.call(obj, 42));
+console.log(Object.hasOwn(obj, 'prop'), Object.hasOwn(obj, 42));
+console.log(Object.hasOwn(obj, 'prop'), Object.hasOwn(obj, 42));
false false
false false
r1-p005 · __proto__ Keys and Prototype Access
1const obj = { __proto__: { toString: 1 }, toString: 'own' };
2console.log(obj.hasOwnProperty('toString'));
3console.log(Object.prototype.hasOwnProperty.call(obj, 'toString'));
--- orig.js	2026-10-17 17:09:35.180991145 -0400
+++ fixed.js	2026-10-17 17:09:35.451993982 -0400
@@ -1,3 +1,3 @@
 const obj = { __proto__: { toString: 1 }, toString: 'own' };
-console.log(obj.hasOwnProperty('toString'));
-console.log(Object.prototype.hasOwnProperty.call(obj, 'toString'));
+console.log(Object.hasOwn(obj, 'toString'));
+console.log(Object.hasOwn(obj, 'toString'));
true
true
r1-p006 · document.all Legacy Quirk
1// Simulating document.all-like object
2const fakeAll = {
3 [Symbol.isConcatSpreadable]: true,
4 toString: () => '',
5 valueOf: () => undefined
6};
7fakeAll.__proto__ = null;
8try {
9 console.log(fakeAll == null, fakeAll.hasOwnProperty('length'));
10} catch (e) {
11 console.log(e.name, e.message);
12}
13try {
14 console.log(fakeAll == null, Object.prototype.hasOwnProperty.call(fakeAll, 'length'));
15} catch (e) {
16 console.log(e.name, e.message);
17}
--- orig.js	2026-10-17 17:09:35.623995783 -0400
+++ fixed.js	2026-10-17 17:09:35.909998778 -0400
@@ -6,12 +6,12 @@
 };
 fakeAll.__proto__ = null;
 try {
-  console.log(fakeAll == null, fakeAll.hasOwnProperty('length'));
+  console.log(fakeAll == null, Object.hasOwn(fakeAll, 'length'));
 } catch (e) {
   console.log(e.name, e.message);
 }
 try {
-  console.log(fakeAll == null, Object.prototype.hasOwnProperty.call(fakeAll, 'length'));
+  console.log(fakeAll == null, Object.hasOwn(fakeAll, 'length'));
 } catch (e) {
   console.log(e.name, e.message);
 }
TypeError fakeAll.hasOwnProperty is not a function
false false
r1-p007 · Non-Function hasOwnProperty Value
1const obj = {};
2Object.defineProperty(obj, 'hasOwnProperty', { value: 42, writable: false });
3try {
4 console.log(obj.hasOwnProperty('x'));
5} catch (e) {
6 console.log(e.name, e.message);
7}
8try {
9 console.log(Object.prototype.hasOwnProperty.call(obj, 'x'));
10} catch (e) {
11 console.log(e.name, e.message);
12}
--- orig.js	2026-10-17 17:09:36.086000620 -0400
+++ fixed.js	2026-10-17 17:09:36.357003457 -0400
@@ -1,12 +1,12 @@
 const obj = {};
 Object.defineProperty(obj, 'hasOwnProperty', { value: 42, writable: false });
 try {
-  console.log(obj.hasOwnProperty('x'));
+  console.log(Object.hasOwn(obj, 'x'));
 } catch (e) {
   console.log(e.name, e.message);
 }
 try {
-  console.log(Object.prototype.hasOwnProperty.call(obj, 'x'));
+  console.log(Object.hasOwn(obj, 'x'));
 } catch (e) {
   console.log(e.name, e.message);
 }
TypeError obj.hasOwnProperty is not a function
false
r1-p008 · this Binding: Arrow vs Function
1const obj = {
2 prop: 'value',
3 check: function() { return this.prop === 'value'; }
4};
5const fn = obj.check;
6console.log(fn());
7try {
8 console.log(obj.hasOwnProperty('check'));
9} catch (e) {
10 console.log(e.name, e.message);
11}
--- orig.js	2026-10-17 17:09:36.522005184 -0400
+++ fixed.js	2026-10-17 17:09:36.782007906 -0400
@@ -5,7 +5,7 @@
 const fn = obj.check;
 console.log(fn());
 try {
-  console.log(obj.hasOwnProperty('check'));
+  console.log(Object.hasOwn(obj, 'check'));
 } catch (e) {
   console.log(e.name, e.message);
 }
r2-p001 · Null/undefined Distinction with Optional Chaining
1let obj = null;
2console.log('obj == null:', obj == null);
3console.log('obj === null:', obj === null);
4try {
5 console.log(obj?.hasOwnProperty('prop'));
6} catch (e) {
7 console.log('Optional chain threw:', e.name, e.message);
8}
9try {
10 console.log(obj.hasOwnProperty('prop'));
11} catch (e) {
12 console.log('Direct call threw:', e.name, e.message);
13}
--- orig.js	2026-10-17 17:09:45.244096410 -0400
+++ fixed.js	2026-10-17 17:09:45.521099305 -0400
@@ -7,7 +7,7 @@
   console.log('Optional chain threw:', e.name, e.message);
 }
 try {
-  console.log(obj.hasOwnProperty('prop'));
+  console.log(Object.hasOwn(obj, 'prop'));
 } catch (e) {
   console.log('Direct call threw:', e.name, e.message);
 }
obj == null: true
obj === null: true
undefined
Direct call threw: TypeError Cannot read properties of null (reading 'hasOwnProperty')
r2-p002 · Getter Side Effect via DefineProperty
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:');
Before:
Getter called
After:
r2-p003 · Async Await Interaction with Property Access
1async function test() {
2 const obj = { awaitPromise: Promise.resolve(42) };
3 console.log('Start');
4 try {
5 const val = await obj.hasOwnProperty('awaitPromise');
6 console.log('Result:', val);
7 } catch (e) {
8 console.log('Caught:', e.name);
9 }
10}
11test().then(() => console.log('Done'));
--- orig.js	2026-10-17 17:09:46.149105867 -0400
+++ fixed.js	2026-10-17 17:09:46.407108563 -0400
@@ -2,7 +2,7 @@
   const obj = { awaitPromise: Promise.resolve(42) };
   console.log('Start');
   try {
-    const val = await obj.hasOwnProperty('awaitPromise');
+    const val = await Object.hasOwn(obj, 'awaitPromise');
     console.log('Result:', val);
   } catch (e) {
     console.log('Caught:', e.name);
Start
Result: true
Done
r2-p004 · Order of Evaluation - Side Effects Doubled
1let count = 0;
2function logArg() {
3 console.log('arg eval', ++count);
4 return 'key';
5}
6const obj = {};
7console.log('Before fix simulation:');
8const prop = obj.hasOwnProperty;
9prop.call(obj, logArg());
10count = 0;
11console.log('\nAfter fix (Biome rewrites):');
12Object.prototype.hasOwnProperty.call(obj, logArg());
--- orig.js	2026-10-17 17:09:46.574110307 -0400
+++ fixed.js	2026-10-17 17:09:46.852113212 -0400
@@ -9,4 +9,4 @@
 prop.call(obj, logArg());
 count = 0;
 console.log('\nAfter fix (Biome rewrites):');
-Object.prototype.hasOwnProperty.call(obj, logArg());
+Object.hasOwn(obj, logArg());
Before fix simulation:
arg eval 1

After fix (Biome rewrites):
arg eval 1
r2-p005 · Property Access Trap Side Effect Lost
1let accessCount = 0;
2const handler = {
3 get(target, prop) {
4 accessCount++;
5 if (prop === 'hasOwnProperty') {
6 console.log('Trap hit for hasOwnProperty, access #', accessCount);
7 return Object.prototype.hasOwnProperty;
8 }
9 return target[prop];
10 }
11};
12const obj = new Proxy({ foo: 1 }, handler);
13accessCount = 0;
14console.log('Before (original):');
15obj.hasOwnProperty('foo');
16console.log('Access count after original:', accessCount);
17accessCount = 0;
18console.log('\nAfter (fixed):');
19Object.prototype.hasOwnProperty.call(obj, 'foo');
20console.log('Access count after fixed:', accessCount);
--- 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);
Before (original):
Trap hit for hasOwnProperty, access # 1
Access count after original: 1

After (fixed):
Access count after fixed: 0
r2-p006 · Argument Evaluation Order Preserved
1let order = [];
2function sideEffect(label) {
3 return () => {
4 order.push(label);
5 return label;
6 };
7}
8const obj = { a: 1 };
9order = [];
10console.log('Original evaluation order:');
11obj.hasOwnProperty(sideEffect('first')());
12console.log('Order:', order.join(' -> '));
13order = [];
14console.log('\nFixed evaluation order:');
15Object.prototype.hasOwnProperty.call(obj, sideEffect('first')());
16console.log('Order:', order.join(' -> '));
--- orig.js	2026-10-17 17:09:47.475119720 -0400
+++ fixed.js	2026-10-17 17:09:47.763122729 -0400
@@ -8,9 +8,9 @@
 const obj = { a: 1 };
 order = [];
 console.log('Original evaluation order:');
-obj.hasOwnProperty(sideEffect('first')());
+Object.hasOwn(obj, sideEffect('first')());
 console.log('Order:', order.join(' -> '));
 order = [];
 console.log('\nFixed evaluation order:');
-Object.prototype.hasOwnProperty.call(obj, sideEffect('first')());
+Object.hasOwn(obj, sideEffect('first')());
 console.log('Order:', order.join(' -> '));
Original evaluation order:
Order: first

Fixed evaluation order:
Order: first
r2-p007 · Non-function hasOwnProperty Value
1const obj = {};
2Object.defineProperty(obj, 'hasOwnProperty', { value: 42, writable: false });
3console.log('obj.hasOwnProperty:', obj.hasOwnProperty);
4try {
5 obj.hasOwnProperty('x');
6} catch (e) {
7 console.log('Original threw:', e.name, ':', e.message);
8}
9try {
10 Object.prototype.hasOwnProperty.call(obj, 'x');
11} catch (e) {
12 console.log('Fixed threw:', e.name, ':', e.message);
13}
--- orig.js	2026-10-17 17:09:47.930124473 -0400
+++ fixed.js	2026-10-17 17:09:48.201127303 -0400
@@ -2,12 +2,12 @@
 Object.defineProperty(obj, 'hasOwnProperty', { value: 42, writable: false });
 console.log('obj.hasOwnProperty:', obj.hasOwnProperty);
 try {
-  obj.hasOwnProperty('x');
+  Object.hasOwn(obj, 'x');
 } catch (e) {
   console.log('Original threw:', e.name, ':', e.message);
 }
 try {
-  Object.prototype.hasOwnProperty.call(obj, 'x');
+  Object.hasOwn(obj, 'x');
 } catch (e) {
   console.log('Fixed threw:', e.name, ':', e.message);
 }
obj.hasOwnProperty: 42
Original threw: TypeError : obj.hasOwnProperty is not a function
r2-p008 · this Binding: Arrow vs Function Method Extraction
1const obj = {
2 value: 42,
3 check: function() {
4 return this.value === 42;
5 },
6 checkArrow: () => {
7 return this.value === 42;
8 }
9};
10const fn = obj.check;
11const arrowFn = obj.checkArrow;
12console.log('Function method call:', obj.check());
13console.log('Extracted function call:', fn());
14console.log('Arrow method call:', obj.checkArrow());
15console.log('Extracted arrow call:', arrowFn());
16try {
17 obj.hasOwnProperty('value');
18} catch (e) {
19 console.log('hasOwnProperty call failed:', e.name);
20}
--- orig.js	2026-10-17 17:09:48.370129069 -0400
+++ fixed.js	2026-10-17 17:09:48.651132003 -0400
@@ -14,7 +14,7 @@
 console.log('Arrow method call:', obj.checkArrow());
 console.log('Extracted arrow call:', arrowFn());
 try {
-  obj.hasOwnProperty('value');
+  Object.hasOwn(obj, 'value');
 } catch (e) {
   console.log('hasOwnProperty call failed:', e.name);
 }
Function method call: true