I ran a small React Native sample app through SonarQube (Community Build 26.10). SonarQube's own analysis found nothing.
The same app has an AWS access key in the JavaScript bundle, a target SDK that hides it from users on newer Android versions, a signing password committed to the repository, and an AppDelegate that will crash in release builds once the New Architecture is on.
None of that is a code smell. It's mobile: store rules, native build files, React Native versions, what ends up inside the app you ship. A general-purpose analyzer doesn't know about it, and it shouldn't have to.
Putting mobile findings into SonarQube
NativeKeel is the free CLI I build for exactly those checks. As of 0.1.93 it can write its findings in SonarQube's generic issue import format, so they land in the project you already have:
npx nativekeel --sonar nativekeel-sonar.json --fail-on never
sonar-scanner -Dsonar.externalIssuesReportPaths=nativekeel-sonar.json
After that, the same sample project looks like this:
Ten issues, each on its file and line, with SonarQube's own categories:
| NativeKeel | Shows up in SonarQube as |
|---|---|
| Leaked keys, signing secrets, security findings | Security · Vulnerability |
| Store rules (Xcode 27 UIScene, Google Play target SDK, 16 KB pages, privacy manifest), crash risks | Reliability · Bug |
| Upgrade blockers, New Architecture, performance, accessibility | Maintainability · Code smell |
In GitHub Actions
steps:
- uses: actions/checkout@v5
- uses: AlicanAkyol/nativekeel@v0
with:
sonar: nativekeel-sonar.json
fail-on: never # let the SonarQube quality gate decide
- uses: SonarSource/sonarqube-scan-action@v8
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: -Dsonar.externalIssuesReportPaths=nativekeel-sonar.json
Two things that tripped me up while testing:
-
Paths. SonarQube attaches each issue to a file it indexed, relative to
sonar.projectBaseDir. Run NativeKeel from that same folder, and keeppackage.json,ios/andandroid/insidesonar.sources. Projects often setsonar.sources=src, and then findings onpackage.jsonorInfo.plisthave nowhere to go. - The first analysis passes the gate anyway. SonarQube's default quality gate looks at new code, and on a project's first analysis nothing counts as new. From the next analysis on, a new NativeKeel finding counts like any other new issue.
What stays out of SonarQube
External rules don't appear in SonarQube's quality profiles, so accepted findings are managed on the NativeKeel side: a .nativekeel.json in the repo lists them, each with a reason, and they stay visible in every NativeKeel report. Malware warnings can't be ignored that way.
Your code stays where it is: NativeKeel runs in your pipeline and writes a JSON file. Only package names go to npm and React Native Directory, and --offline sends nothing.
Setup page with the details: nativekeel.com/sonarqube. If your team runs SonarQube on mobile apps, I'd like to hear what else you'd want to see in it.


Top comments (0)