How accurate is NativeKeel?

A scanner earns trust by what it gets right, not by how many checks it lists. These are the measurements behind NativeKeel's checks, including what it misses. Updated 20 October 2026.

Finds: problems we planted

A React Native 0.87 test app with 41 known problems, each in its own file (security, performance, stability). NativeKeel found 24 of them fully and 1 partly in 0.1.104, and 31 fully and 1 partly (76%) from 0.1.105. Of the 9 it misses, 4 are left out on purpose: copying a password to the clipboard is a feature users ask for; SQL built from a value whose source cannot be traced proves nothing; a client-side role check is not a hole while the server enforces it; a new object passed to a Context provider rarely matters. The other 5 need runtime or data-flow information a static scan does not have: a long list rendered with map inside a ScrollView, a FlatList without keyExtractor, JSON.parse without try, no error boundary, and a deep link URL fetched without checking its host.

Finds: vulnerabilities other people found

Ten published cases in scope for static analysis: GitHub security advisories of React Native apps, and commits in React Native repositories that removed a leaked key, each scanned at the commit before the fix. Found: 5 before 0.1.107, 7 after. It reports Rocket.Chat's exported reply receiver (GHSA-gwg8-fvp7-mp2x) on the vulnerable release and not on the fixed one, Sentry's Expo plugin token (GHSA-68c2-4mpx-qh95), and Jellyfin's pull_request_target workflow (GHSA-7qhm-2m45-7fmh) before its fix and not after. It misses Zulip's link check done with a string prefix (CVE-2022-35962) and two app-specific API keys whose name and format look like public keys.

False alarms: every new finding reviewed by hand

Before a check ships, it runs on 1,000+ open-source React Native and Expo apps, every finding it adds is opened in the source, and the check is tightened until what remains is right. Examples from October 2026:

CheckFirst versionShipped
URL trusted after a text comparison52 apps, mostly harmless "is this a YouTube link" tests3 apps, 3 confirmed (a payment WebView, a reCAPTCHA WebView, a video player)
Credentials in release logs55 apps (server code, push tokens, !!token flags)25 apps, reviewed one by one
Timers and listeners that can never be stopped13 findings13 confirmed
Images nothing references394 apps245 reported images sampled, none in use
Source files nothing imports161 apps, wrong when an alias could not be readstays quiet unless every import resolves
Hermes bundle secrets32 CSS names taken for OpenAI keys0 in 20 open-source bundles; planted keys found
Script injection in GitHub Actions3 workflows, all guarded0; 12 public workflows that use issue titles correctly pass
Supabase tables of people readable by anyonewould have reported a hospital's public phone column2 apps, both confirmed in their migrations

A production app review in October 2026 found four false alarms (an inherited AppDelegate window, Folly flags set in the Podfile, logging removed by the project's own Babel plugin, a server-only moment advisory). All four were fixed in 0.1.111.

What every finding tells you

Severity says how bad the outcome would be. Separately, each finding says what it rests on: a configuration file (manifest, plist, build file, rules), source code (whether that code runs was not verified), code the app never imports (lowered and labelled), the built app, or package versions. In a team's .nativekeel.json, gate picks which checks may fail the build, and an accepted finding can carry an until date so it comes back for review.

Known blind spots

Zero findings is never a certificate. The test app and the corpus scripts are run again with every change to the checks; when a number above changes, this page changes with it.