key native functions are untampered (toString + no prototype)
Check id native-integrity
What an ordinary browser yields
All present targets stringify as native and expose no .prototype; pass.
What a detector infers
This runs a battery over roughly forty engine-owned callables — canvas, WebGL, navigator, iframe, shadow-DOM and fetch natives, plus the JS core (Object.*, Reflect.*, Function.prototype bind/call/apply, JSON.stringify and the constructors) — and applies up to three tests to each. First the [native code] stringification marker. Then, on V8 only, byte-exact equality against an engine-derived template of what a native function's source text must look like: the template is self-validated against just three constructors, and the live audit corpus showed that exactness false-positiving on 100% of genuine Firefox and Safari (SpiderMonkey/JavaScriptCore format some natives differently), so off V8 the marker test alone carries the check — wrappers and shims are still caught, formatting quirks are no longer punished. Last, `'prototype' in fn`: built-in methods and accessors are non-constructors and per spec carry no .prototype property, whereas an ordinary `function(){}` used as a wrapper gets one automatically — a shim that returns a convincing string from toString can still be given away by a .prototype the original never had. Targets that aren't functions in this browser are skipped rather than failed, so an unsupported API doesn't count against the result.
How to resolve it
Each entry named in the failure detail is a built-in that has been replaced or wrapped by a JavaScript function. Replace the wrapper approach with engine-level control of the underlying value. Note what this battery does and does not cover: an arrow function or a method-shorthand avoids the .prototype tell but still returns its own source from toString, while a Proxy around the original passes both probes — the engine stringifies a proxied callable as a NativeFunction and forwards the 'prototype' lookup to the native target. Proxied wrappers are surfaced by the descriptor-shape and cross-realm checks instead.
Read in the wild by
PerimeterX / HUMAN
Stringifies engine-owned callables and ships the result two ways: a [native code] regex test for setTimeout, setInterval, Function.prototype.bind and getComputedStyle, and a 32-bit hash of the function source for Object.prototype.toString, Object.getOwnPropertyDescriptor, localStorage.setItem, documentElement.dispatchEvent and console.log.
main.min.js: `function kz(t){return hR(t)===ie&&new RegExp("\\{\\s*\\[native code\\]\\s*\\}","").test(""+t)}` (ie="function") — a boolean native-code test — applied as `t["YQ1UByRqUzE="]=kz(hS.setTimeout)`, `t["KxseEW16HCU="]=kz(hS.setInterval)`, `t["b19aVSk/X2c="]=kz(Function[hQ(275)].bind)`, `t["eEQNDj0lCzU="]=hT[hQ(826)]&&kz(hT[hQ(826)].getComputedStyle)` (hQ(275)='prototype', hQ(826)='defaultView'). Separately, in `function Ck(t)`: `kD(t,"PSkIY3tJCVg=",(function(){return BS(hS.console[hQ(753)])}),"")`, `kD(t,hQ(755),(function(){return BS(Object.prototype.toString)}),"")`, `kD(t,"b19aVSkzXW4=",(function(){return BS(Object[hQ(698)])}),"")`, `kD(t,hQ(767),(function(){return BS(hS.localStorage[hQ(419)])}),"")`, `kD(t,hQ(765),(function(){return BS(hT.documentElement[hQ(766)])}),"")` — where `function BS(t){if(hR(t)!==hW)return kn(t)}` and `function kn(t){t=""+t;for(var n=kk,e=0;e<t.length;e++){n=(n<<5)-n+t.charCodeAt(e),n|=0}return kJ(n)}` (kk=0; `kJ` renders the uint32 as hex), i.e. a hash of the function source. hQ(753)='log', hQ(698)='getOwnPropertyDescriptor', hQ(419)='setItem', hQ(766)='dispatchEvent'.
CreepJS
CreepJS, a research demo rather than a production detector, pairs the native-code stringification with the exact same `'prototype' in fn` non-constructor test, and applies it to targets including Permissions.query, CanvasRenderingContext2D.getImageData and HTMLIFrameElement.contentWindow.
src/lies/index.ts:200 `['failed "prototype" in function']: 'prototype' in apiFunction,` — an adjacent key, in the same lies object and on the same apiFunction, to the native-code test at :196-199 `['failed toString']: (!hasKnownToString(name)[scope.Function.prototype.toString.call(apiFunction)] || …)`. Targets reaching that object via searchLies: :726 `searchLies(() => Permissions, { target: ['query'] })`; :494 `searchLies(() => CanvasRenderingContext2D, { target: ['getImageData', 'getLineDash', 'isPointInPath', …] })`; :626 `searchLies(() => HTMLIFrameElement, { target: ['contentDocument', 'contentWindow'] })`. Accessor targets are covered too: :413-419 extracts the getter via `Object.getOwnPropertyDescriptor(proto, name).get` and passes it through the same queryLies. Also src/headless/index.ts:136-138: `if ('prototype' in chrome.runtime.sendMessage || 'prototype' in chrome.runtime.connect) { return true }`.
Kasada
Spends 23 probes on the language builtins rather than the DOM: the natives a spoof rewrites the DOM WITH.
prop_recorder_to_string, prop_recorder_bind, prop_recorder_call, prop_recorder_apply, prop_recorder_new_function, prop_recorder_own_descriptors, prop_recorder_proxy, prop_recorder_error_constructor, …
Kasada ips.js teardown — the full 427-probe listEvery attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Native function integrity
- Function.toString not proxied (native code)
tostring-nativeThe check stringifies two functions and requires both to match /\{\s*\[native code\]\s*\}/: Function.prototype.toString itself (read as… - navigator props resolve via native prototype getters
navigator-descriptorsFor deviceMemory, hardwareConcurrency, language, languages and platform, the check reads the property descriptor twice. - a fresh iframe (contentWindow) matches the main realm
iframe-coherenceThe check appends a hidden same-origin iframe to documentElement and reads its contentWindow — a brand-new JavaScript realm with its own… - Worker navigator matches the main thread
worker-navigator-coherenceA Blob-URL Worker is spawned and reports its own navigator.platform, navigator.hardwareConcurrency, navigator.webdriver and… - page-world natives that extensions commonly wrap
page-world-wrappersThis probe stringifies window.fetch and window.Request and asks whether each still renders as native code, then checks whether document… - nonexistent navigator properties return undefined
navigator-proxy-honeypotThis reads five navigator property names that exist on no browser — rml, ln, rnd, webdriverPatched and __clearcoteProbe — and additionally… - native methods enforce their C++ receiver check
native-brand-checksTwo native methods are invoked with their own bare prototype as the receiver… - iframe srcdoc/src/contentWindow live on the prototype
iframe-srcdoc-placementA fresh <iframe> is created with document.createElement and inspected for own property descriptors on srcdoc, src and contentWindow.
Clearcote is a browser built for fingerprint coherence
It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.
This audit takes no position on how Clearcote scores on Native function integrity checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.
See the other checks in Native function integrity — the family native-integrity belongs to.