Function.toString not proxied (native code)
Check id tostring-native
What an ordinary browser yields
Both probes return the native-code placeholder; pass.
What a detector infers
The check stringifies two functions and requires both to match /\{\s*\[native code\]\s*\}/: Function.prototype.toString itself (read as Function.prototype.toString.toString()), and navigator.permissions.query as a spot-check target. Per spec, a function implemented by the engine has no JavaScript source to return, so toString yields the NativeFunction placeholder; a function defined in JS returns its own source text. A userland layer that wraps a built-in has to keep the wrapper looking native, so it typically replaces Function.prototype.toString with a JS function that special-cases the wrapper — and that replacement returns its own source text, which is exactly what the first probe reads. The second probe covers the simpler case where permissions.query itself was swapped for a JS function. A detector that sees Function.prototype.toString reporting JS source infers that something in the page is actively rewriting the identity of its built-ins, which is a stronger signal than whatever the wrapper was concealing. This is a naive-tamper probe by design: a well-formed Proxy around the original is stringified by the engine as a NativeFunction and passes both probes, so proxied wrappers have to be caught by the other checks in the battery (descriptor shape, cross-realm reads).
How to resolve it
The contradiction comes from a JS-injection stealth layer proxying or wrapping Function.prototype.toString. Remove userland evasion shims that patch toString and let identity control happen at the engine level, where built-ins are genuinely native and stringify as such with no wrapper to hide. Note both probes are wrapped in safe(..., true), so a probe that throws is treated as a pass rather than a tell.
Read in the wild by
Kasada
Kasada's ips.js carries a helper that takes a function as its argument, stringifies it with Function.prototype.toString, and returns whether the result contains "[native code]" — falling back to a typeof check if the stringification throws.
Kasada ips.js decompile, 1.txt:37974-37987 — func_028a4b(a0): `var _215 = a0; r7 = globalThis.Function; r8 = r7.toString; r6 = r8.call(_215); r2 = r6.indexOf("[native code]"); r7 = -1 !== r2; return r7;`. Its catch handler at 1.txt:37994-38003 falls back to `r5 = typeof _215; r4 = "function" == r5; return r4`, confirming the argument is the function under test. The same helper appears in the second script version at 3.txt:39187-39200, and in 2.txt:22008-22021 as func_014375 (where the decompiler mis-renders the call as `r7.apply(r7, _48)`). Registered in the helper table at 1.txt:279 (`_fn_27 = func_028a4b`) and 2.txt:130 (`_fn_17 = func_014375`). Corpus provenance: CONTEXT.md:40-42 (1.txt/2.txt/3.txt = IR + decompiles of Kasada ips.js).
PerimeterX / HUMAN
Tests engine-owned callables for the [native code] placeholder: Function.prototype.bind and Function.prototype.call via a regex byte-identical to this check's, and navigator.permissions.query via an anchored variant that stringifies through Function.prototype.toString.call. When permissions.query is not native it uploads the first 1024 characters of the wrapper's own source text; when Function.prototype.call is not native it uploads a hash of its source.
Deployed collector main.min.js (PerimeterX, iFood deployment; sha256 e042d5de83…a754e). Unanchored test, regex byte-identical to this check's: `function kz(t){return hR(t)===ie&&new RegExp("\\{\\s*\\[native code\\]\\s*\\}","").test(""+t)}` — applied to `Function[hQ(275)].bind` (hQ(275)='prototype') and, in `AU()`, to `hS[jb("RnVuY3Rpb24=")][jb("cHJvdG90eXBl")][jb(hQ(689))]` (= Function.prototype.call; hQ(689)='Y2FsbA=='), with `if(!kz(r))return kn(r+"")` where `kn` is a `(n<<5)-n+t.charCodeAt(e)` hash emitted as field "WGRtbh4Ca1s=". Separate anchored test: `function xC(t){try{return!!xE(t).match(new RegExp("\\{\\s*\\[native code\\]\\s*\\}$","m"))}catch(t){return!1}}` where `xE` = Function.prototype.toString.call; it gates `function xx(t){...xC(hU.permissions.query)||(t[hQ(373)]=hU[hQ(367)][hQ(368)][hQ(247)]()[hQ(332)](0,1024))...}` with hQ(367/368/247/332)='permissions'/'query'/'toString'/'substring' and hQ(373)='RlZzHAM2eS4=' (field key). String-table decodes corroborated by bug_report/sdk_drift_cases/2026-05-19_ifood/hQ_map.json; same construct recurs in the Walmart (ho/up) and Total Wine (kT) deployments under different mangling.
CreepJS
CreepJS — an open-source research demo rather than a production detector — stringifies each API against a table of six accepted `[native code]` forms and flags any mismatch as `failed toString`; it searches Function.prototype.toString first and uses that result, alongside Permissions.query, to gate its deeper proxy battery, surfacing the outcome as a named stealth signal, `hasToStringProxy`.
src/lies/index.ts: `function hasKnownToString(name) { return { [`function ${name}() { [native code] }`]: true, [`function get ${name}() { [native code] }`]: true, … } }`; `['failed toString']: (!hasKnownToString(name)[scope.Function.prototype.toString.call(apiFunction)] || !hasKnownToString('toString')[scope.Function.prototype.toString.call(apiFunction.toString)])`; `searchLies(() => Function, { target: ['toString'], ignore: ['caller', 'arguments'] })` — the first of 39 searchLies calls; `const detectProxies = (name == 'toString' || !!lieProps['Function.toString'] || !!lieProps['Permissions.query'])` gating the advanced proxy tests. src/headless/index.ts: `stealth: { …, hasToStringProxy: (!!lieProps['Function.toString']), … }`, feeding `stealthRating`.
Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Native function integrity
- navigator props resolve via native prototype getters
navigator-descriptorsFor deviceMemory, hardwareConcurrency, language, languages and platform, the check reads the property descriptor twice. - key native functions are untampered (toString + no prototype)
native-integrityThis runs a battery over roughly forty engine-owned callables — canvas, WebGL, navigator, iframe, shadow-DOM and fetch natives, plus the JS… - 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 tostring-native belongs to.