# biome suspicious/noPrototypeBuiltins: fix changes program behavior

Internal evidence sheet generated by fixhunt. Not an issue text. A human re-verifies, checks the duplicates
below, and writes the upstream report in their own words following the project's AI policy.

- Tool: biome 2.5.15
- Rule: suspicious/noPrototypeBuiltins (tool labels the fix: safe, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): intended-change, severity 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.
- Program: minimized from 10 to 8 lines

## Reproducer

```js
const obj = {};
Object.defineProperty(obj, 'hasOwnProperty', {
  get() {
    console.log('Getter called');
    return Object.prototype.hasOwnProperty;
  }
});
obj.hasOwnProperty('x');
```

## Commands

```sh
node prog.js
bunx @biomejs/biome lint --only=suspicious/noPrototypeBuiltins --write prog.js
node prog.js
```

## Observed

```
stdout before:
Getter called
stdout after:
```

## Diff applied by the fix

```diff
--- orig.js	2026-10-22 13:36:54.392511452 -0400
+++ fixed.js	2026-10-22 13:36:56.473546617 -0400
@@ -5,4 +5,4 @@
     return Object.prototype.hasOwnProperty;
   }
 });
-obj.hasOwnProperty('x');
+Object.hasOwn(obj, 'x');
```

## Why the rewrite is not equivalent (model draft, verify before use)

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.

## Upstream search

Queries: "noPrototypeBuiltins fix", "suspicious noPrototypeBuiltins hasOwnProperty call", "biome lint rule suspicious noPrototypeBuiltins override", "Object.defineProperty redefines hasOwnProperty getter"

- related: https://github.com/biomejs/biome/issues/10769
  useLiteralKeys rule flags __proto__ in computed member expression, same rule family (prototype builtins) but different construct

<details><summary>All hits</summary>

- [github, open] 💅 `useSortedProperties` can produce invalid CSS when the final semicolon is omitted — https://github.com/biomejs/biome/issues/12417
- [github, open] 💅 `useSortedProperties` moves Sass variable declarations below their uses — https://github.com/biomejs/biome/issues/12414
- [github, open] 💅 `useSortedProperties` can change behavior when reordering nested CSS rules — https://github.com/biomejs/biome/issues/12413
- [github, open] 💅 `noUnnecessaryConditions`: false positive on an overloaded call with `undefined` as the default argument (Vue `inject`) — https://github.com/biomejs/biome/issues/12040
- [github, open] 💅 `noSkippedTests` conditionally skip fix suggestion — https://github.com/biomejs/biome/issues/9295
- [github, open] 💅 Actually used private method considered unused — https://github.com/biomejs/biome/issues/8185
- [github, open] 💅 cannot detect that the StrictMode component of React is being exported. — https://github.com/biomejs/biome/issues/10609
- [github, open] 💅 noUnnecessaryConditions callback overload false positive — https://github.com/biomejs/biome/issues/11439
- [github, open] 💅 lint/a11y/useAnchorContent: the PascalCase component allowance is applied only to self-closing elements — https://github.com/biomejs/biome/issues/11872
- [github, open] 💅 useLiteralKeys flags `__proto__` in a computed member expression and offers an unsafe fix that conflicts with noProto — https://github.com/biomejs/biome/issues/10769
- [github, closed] 💅 `noThisInStatic` safe fix is not safe — https://github.com/biomejs/biome/issues/10011
- [github, open] 💅 When using useNamingConvention, prefix and suffix functionality cannot be used in destructuring assignment renaming. — https://github.com/biomejs/biome/issues/8953
- [github, closed] 🐛 Svelte: reordering imports assumes `{ "indentScriptAndStyle": false }` and ignores current indentation — https://github.com/biomejs/biome/issues/9194
- [github, closed] 💅 `useFilenamingConvention` override not applying to TanStack Start splat route files ($.ts, rpc.$.ts) — https://github.com/biomejs/biome/issues/9082
- [github, closed] 💅 useConsistentTypeDefinitions should ignore interfaces in global declarations — https://github.com/biomejs/biome/issues/8449
- [github, closed] 📝 CSS comment gets reformated without proper indentation — https://github.com/biomejs/biome/issues/11228
- [github, closed] 💅 useLiteralKeys override not working — https://github.com/biomejs/biome/issues/6736
- [github, closed] 💅 Linter: `lint --write` is not idempotent on Astro frontmatter, while `lint` reports no issues — https://github.com/biomejs/biome/issues/7912
- [github, closed] unknownAtRules error for tailwind v4 — https://github.com/biomejs/biome/issues/7223
- [github, closed] 💅 Nest.js app breaks with useImportType rule — https://github.com/biomejs/biome/issues/4514
- [github, closed] 💅 Overriding linter rules in nested conf file (monorepo) — https://github.com/biomejs/biome/issues/6434

</details>
