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:
| Check | First version | Shipped |
|---|---|---|
| URL trusted after a text comparison | 52 apps, mostly harmless "is this a YouTube link" tests | 3 apps, 3 confirmed (a payment WebView, a reCAPTCHA WebView, a video player) |
| Credentials in release logs | 55 apps (server code, push tokens, !!token flags) | 25 apps, reviewed one by one |
| Timers and listeners that can never be stopped | 13 findings | 13 confirmed |
| Images nothing references | 394 apps | 245 reported images sampled, none in use |
| Source files nothing imports | 161 apps, wrong when an alias could not be read | stays quiet unless every import resolves |
| Hermes bundle secrets | 32 CSS names taken for OpenAI keys | 0 in 20 open-source bundles; planted keys found |
| Script injection in GitHub Actions | 3 workflows, all guarded | 0; 12 public workflows that use issue titles correctly pass |
| Supabase tables of people readable by anyone | would have reported a hospital's public phone column | 2 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
- Behaviour at run time: crashes, frame drops and start-up time need a device.
- Your server: API authorization, and Firebase or Supabase rules that live only in the console.
- Data flow across files: a token passed through several functions before it is logged.
- iOS native code paths (Android native Intent flows are checked).
- Supabase migrations with dynamic SQL or blocks that drop policies: 17 of 45 open-source databases are skipped rather than guessed.
- Keys without a recognisable format, named like public keys.
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.