<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: alican akyol</title>
    <description>The latest articles on DEV Community by alican akyol (@keel_alican_akyol).</description>
    <link>https://dev.to/keel_alican_akyol</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4167230%2F4a64f202-b8b7-4431-96f7-051f9404d054.png</url>
      <title>DEV Community: alican akyol</title>
      <link>https://dev.to/keel_alican_akyol</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/keel_alican_akyol"/>
    <language>en</language>
    <item>
      <title>We scanned 470 open-source React Native apps. Here is what breaks them.</title>
      <dc:creator>alican akyol</dc:creator>
      <pubDate>Tue, 06 Oct 2026 19:14:13 +0000</pubDate>
      <link>https://dev.to/keel_alican_akyol/we-scanned-470-open-source-react-native-apps-here-is-what-breaks-them-5072</link>
      <guid>https://dev.to/keel_alican_akyol/we-scanned-470-open-source-react-native-apps-here-is-what-breaks-them-5072</guid>
      <description>&lt;p&gt;I build a free CLI, &lt;code&gt;npx nativekeel&lt;/code&gt;, that checks React Native and Expo apps for the problems that turn a routine upgrade into a three-week project. To keep its false alarms down, I run it on every open-source React Native app I can find. The test set is now 470 apps, from abandoned 2019 demos to large production apps like wallets, chat clients and note-taking apps.&lt;/p&gt;

&lt;p&gt;Old apps fail in boring, expected ways: unsupported versions, the New Architecture off, Google Play's target SDK missed. So the numbers below are for the 194 apps that are already on &lt;strong&gt;React Native 0.76 or newer&lt;/strong&gt;. These are apps whose developers keep them up to date, and they still have these problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we found in up-to-date apps
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Share of up-to-date apps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A dependency with a known high or critical vulnerability in the exact version shipped&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;21%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Still on React Native 0.76, which is not ready for 16 KB memory pages (Google Play requires this since Nov 2025 for apps targeting Android 15+; 0.77 fixes it)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;16%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The template URL scheme &lt;code&gt;myapp://&lt;/code&gt; still in place&lt;/td&gt;
&lt;td&gt;14%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30+ &lt;code&gt;console.log&lt;/code&gt; calls shipped in the release build&lt;/td&gt;
&lt;td&gt;13%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Whole-library &lt;code&gt;lodash&lt;/code&gt; or &lt;code&gt;moment&lt;/code&gt; imports&lt;/td&gt;
&lt;td&gt;12%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Images over 500 KB required by the app&lt;/td&gt;
&lt;td&gt;9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A secret committed to the repo or compiled into the bundle (cloud API keys, release signing passwords, tokens in &lt;code&gt;eas.json&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;5%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Across all 470 apps, including the old ones: 58% still have the New Architecture off, which means they cannot go past React Native 0.81. 28% target an Android SDK that Google Play no longer accepts for updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four findings worth checking in your own app today
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Expo config is not a safe place for secrets.&lt;/strong&gt; Anything in &lt;code&gt;app.json&lt;/code&gt; → &lt;code&gt;extra&lt;/code&gt;, and every &lt;code&gt;EXPO_PUBLIC_&lt;/code&gt; variable, ships inside the app and can be read by anyone who downloads it. And &lt;code&gt;eas.json&lt;/code&gt; is committed with your code: three apps had a Sentry auth token in its build &lt;code&gt;env&lt;/code&gt;, which can read and change the whole Sentry organisation. Public SDK keys (RevenueCat, Firebase web config) are fine. Server keys belong in EAS secrets (&lt;code&gt;eas env:create&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. &lt;code&gt;myapp://&lt;/code&gt; is shared with every other app that kept it.&lt;/strong&gt; The Expo template sets &lt;code&gt;"scheme": "myapp"&lt;/code&gt;. If you sign in with &lt;code&gt;expo-auth-session&lt;/code&gt;, Clerk or AppAuth, the OAuth redirect goes to &lt;code&gt;myapp://&lt;/code&gt;, and on Android any other installed app with the same scheme can show up to receive it. Use a scheme unique to your app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Unverified App Links open in the browser.&lt;/strong&gt; An &lt;code&gt;https://your.domain/...&lt;/code&gt; intent filter without &lt;code&gt;android:autoVerify="true"&lt;/code&gt; (and a matching &lt;code&gt;assetlinks.json&lt;/code&gt;) opens in the browser on Android 12+, not in your app. On older Android, any app can register the same link. This matters most for login, password reset and invite links.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Passwords travel further than you think.&lt;/strong&gt; The leak that surprised us most was not a hacked server. It was a password that ended up in a crash report or analytics event after passing through a couple of variables (&lt;code&gt;const info = email + ':' + password; track('signup_failed', { info })&lt;/code&gt;). Searching for &lt;code&gt;password&lt;/code&gt; next to &lt;code&gt;track(&lt;/code&gt; does not find it; you have to follow the variable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we got wrong, and fixed
&lt;/h2&gt;

&lt;p&gt;Scanning real apps is mostly about finding where the tool is wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A wallet app installed a package from git that has the same name as an npm package with a malware advisory. Git dependencies are now never matched against npm advisories.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.DS_Store&lt;/code&gt; files caught in a patch-package patch are harmless. They are no longer reported as "build output that will not apply".&lt;/li&gt;
&lt;li&gt;Android verifies every web host when &lt;em&gt;any&lt;/em&gt; intent filter has &lt;code&gt;autoVerify&lt;/code&gt;. Our first deep-link check missed that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every release lists what changed: &lt;a href="https://nativekeel.com/changelog" rel="noopener noreferrer"&gt;https://nativekeel.com/changelog&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nativekeel            &lt;span class="c"&gt;# report in the terminal&lt;/span&gt;
npx nativekeel plan       &lt;span class="c"&gt;# an ordered upgrade plan&lt;/span&gt;
npx nativekeel &lt;span class="nt"&gt;--html&lt;/span&gt; report.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It runs locally. Your code never leaves your machine: the only network calls are package-name lookups and the same advisory request &lt;code&gt;npm audit&lt;/code&gt; makes. It has zero dependencies, publishes with npm provenance, and is MIT licensed. There is also a GitHub Action that adds findings to pull requests.&lt;/p&gt;

&lt;p&gt;These are static checks. They find the common, detectable mistakes, but they are not a penetration test. A clean report means none of these known problems, not "unhackable".&lt;/p&gt;

&lt;p&gt;If something it reports is wrong for your app, please open an issue on GitHub. False alarms are the bugs I care about most: &lt;a href="https://github.com/AlicanAkyol/nativekeel" rel="noopener noreferrer"&gt;https://github.com/AlicanAkyol/nativekeel&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>expo</category>
      <category>mobile</category>
      <category>security</category>
    </item>
  </channel>
</rss>
