rn-security-audit
React Native Security Audit
Identify vulnerabilities and sensitive data exposure in React Native apps.
Quick Scan Commands
Find Hardcoded Secrets
# API keys and tokens
grep -rniE "(api[_-]?key|apikey|api[_-]?secret|access[_-]?token|auth[_-]?token|bearer|private[_-]?key|secret[_-]?key)\s*[:=]\s*['\"][a-zA-Z0-9]" --include="*.js" --include="*.ts" --include="*.tsx" --include="*.jsx" .
# AWS credentials
grep -rniE "(AKIA|ASIA)[A-Z0-9]{16}" --include="*.js" --include="*.ts" --include="*.json" .
grep -rniE "aws[_-]?(secret|access|key)" --include="*.js" --include="*.ts" --include="*.json" .
# Firebase/Google
grep -rniE "(AIza[0-9A-Za-z\-_]{35})" .
grep -rniE "firebase.*['\"][a-zA-Z0-9\-]+\.firebaseio\.com" .
# Generic secrets
grep -rniE "(password|passwd|pwd|secret)\s*[:=]\s*['\"][^'\"]{4,}" --include="*.js" --include="*.ts" --include="*.tsx" .
# Private keys
grep -rniE "-----BEGIN (RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY" .
# JWT tokens (hardcoded)
grep -rniE "eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*" .
Find PII Exposure
# Email patterns in code
grep -rniE "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" --include="*.js" --include="*.ts" .
# Phone numbers
grep -rniE "(\+?1?[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}" --include="*.js" --include="*.ts" .
# SSN patterns
grep -rniE "\b\d{3}[-]?\d{2}[-]?\d{4}\b" --include="*.js" --include="*.ts" .
# Credit card patterns
grep -rniE "\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\b" .
# Console.log with sensitive data
grep -rniE "console\.(log|debug|info|warn)\s*\([^)]*?(password|token|secret|key|credential|ssn|credit)" --include="*.js" --include="*.ts" --include="*.tsx" .
Find Insecure Patterns
# HTTP (not HTTPS)
grep -rniE "http://(?!localhost|127\.0\.0\.1|10\.|192\.168\.)" --include="*.js" --include="*.ts" --include="*.json" .
# Disabled SSL verification
grep -rniE "(rejectUnauthorized|SSL_VERIFY|verify.*false)" --include="*.js" --include="*.ts" .
# eval() usage
grep -rniE "\beval\s*\(" --include="*.js" --include="*.ts" --include="*.tsx" .
# innerHTML (XSS risk)
grep -rniE "(innerHTML|dangerouslySetInnerHTML)" --include="*.js" --include="*.ts" --include="*.tsx" .
# AsyncStorage (unencrypted)
grep -rniE "AsyncStorage\.(setItem|getItem|multiSet).*?(password|token|secret|key|credential)" --include="*.js" --include="*.ts" .
# Insecure random
grep -rniE "Math\.random\s*\(\)" --include="*.js" --include="*.ts" .
Vulnerability Categories
1. Hardcoded Secrets (CRITICAL)
What to find:
- API keys, tokens, passwords in source code
- Credentials in config files committed to repo
- Secrets in environment files checked into git
Check files:
# Common locations for leaked secrets
cat .env .env.local .env.development .env.production 2>/dev/null
cat app.json app.config.js babel.config.js metro.config.js 2>/dev/null
cat ios/*/Info.plist android/app/src/main/AndroidManifest.xml 2>/dev/null
Remediation:
// BAD
const API_KEY = "sk-1234567890abcdef";
// GOOD - use environment variables
import Config from 'react-native-config';
const API_KEY = Config.API_KEY;
// GOOD - use secure storage for runtime secrets
import * as Keychain from 'react-native-keychain';
await Keychain.setGenericPassword('api', token);
2. Insecure Data Storage (HIGH)
Vulnerable patterns:
// INSECURE - AsyncStorage is unencrypted
await AsyncStorage.setItem('userToken', token);
await AsyncStorage.setItem('password', password);
// INSECURE - Storing in state/redux persistor unencrypted
const persistConfig = {
key: 'root',
storage: AsyncStorage, // Unencrypted!
whitelist: ['auth'] // Contains tokens!
};
Check for:
# Find AsyncStorage usage with sensitive data
grep -rniE "AsyncStorage" --include="*.js" --include="*.ts" -A2 -B2 | grep -iE "(token|password|secret|key|auth|credential|session)"
# Check Redux persist config
grep -rniE "persistConfig|persistReducer" --include="*.js" --include="*.ts" -A10
Secure alternatives:
// iOS Keychain / Android Keystore
import * as Keychain from 'react-native-keychain';
await Keychain.setGenericPassword('user', token);
// Encrypted storage
import EncryptedStorage from 'react-native-encrypted-storage';
await EncryptedStorage.setItem('token', token);
// Expo SecureStore
import * as SecureStore from 'expo-secure-store';
await SecureStore.setItemAsync('token', token);
3. Network Security (HIGH)
Check for:
# Find all URLs
grep -rniE "(https?://[^\s'\"]+)" --include="*.js" --include="*.ts" -o | sort -u
# Find fetch/axios configs
grep -rniE "(fetch|axios)\s*\(" --include="*.js" --include="*.ts" -A5
# Check for certificate pinning
grep -rniE "(pinning|certificate|ssl)" --include="*.js" --include="*.ts"
Vulnerable patterns:
// INSECURE - No HTTPS
fetch('http://api.example.com/data');
// INSECURE - Disabled cert verification
const agent = new https.Agent({ rejectUnauthorized: false });
// INSECURE - No timeout
fetch(url); // Can hang indefinitely
Secure patterns:
// SECURE - HTTPS with certificate pinning
import { fetch } from 'react-native-ssl-pinning';
fetch(url, {
sslPinning: {
certs: ['cert1', 'cert2']
},
timeoutInterval: 10000
});
4. Authentication & Session (HIGH)
Check for:
# Find auth-related code
grep -rniE "(login|logout|authenticate|authorize|session|jwt|oauth)" --include="*.js" --include="*.ts" -l
# Check token handling
grep -rniE "(access.?token|refresh.?token|bearer|authorization)" --include="*.js" --include="*.ts" -A3 -B3
# Find biometric auth
grep -rniE "(biometric|fingerprint|faceid|touchid)" --include="*.js" --include="*.ts"
Vulnerable patterns:
// INSECURE - Token in URL
fetch(`https://api.com/data?token=${token}`);
// INSECURE - No token refresh
const token = await getToken(); // Never refreshes
// INSECURE - Logging tokens
console.log('Auth token:', token);
// INSECURE - Token in error messages
throw new Error(`Auth failed for token: ${token}`);
5. Input Validation & Injection (MEDIUM)
Check for:
# Find dynamic queries
grep -rniE "(query|sql|execute).*\$\{" --include="*.js" --include="*.ts"
# Find WebView usage
grep -rniE "WebView|injectJavaScript|postMessage" --include="*.js" --include="*.tsx"
# Find deep linking
grep -rniE "(Linking|DeepLink|universal.?link)" --include="*.js" --include="*.ts"
Vulnerable patterns:
// INSECURE - SQL injection via string concatenation
db.execute(`SELECT * FROM users WHERE id = ${userId}`);
// INSECURE - WebView JavaScript injection
webViewRef.current.injectJavaScript(`
document.getElementById('data').innerHTML = '${userInput}';
`);
// INSECURE - Deep link without validation
Linking.addEventListener('url', ({ url }) => {
const route = url.split('/')[1];
navigation.navigate(route); // No validation!
});
6. Logging & Debugging (MEDIUM)
Check for:
# Find all console statements
grep -rniE "console\.(log|debug|info|warn|error|trace)" --include="*.js" --include="*.ts" --include="*.tsx"
# Find debug flags
grep -rniE "(__DEV__|debug|DEBUG|devMode)" --include="*.js" --include="*.ts"
# Check for React Native Debugger/Flipper
grep -rniE "(flipper|reactotron|debug)" package.json
# Find error boundaries logging
grep -rniE "componentDidCatch|ErrorBoundary" --include="*.js" --include="*.tsx" -A10
Vulnerable patterns:
// INSECURE - Logging sensitive data
console.log('User data:', userData);
console.log('Request:', { headers: { Authorization: token }});
// INSECURE - Debug code in production
if (__DEV__) {
// This still ships in JS bundle!
}
7. Third-Party Dependencies (MEDIUM)
Check for:
# Audit npm packages
npm audit
npm audit --json > npm-audit.json
# Check for outdated packages
npm outdated
# Find known vulnerable packages
npx check-my-deps
# List all dependencies
cat package.json | jq '.dependencies, .devDependencies'
High-risk packages to review:
- Any package with native code
- Packages accessing: camera, location, contacts, storage
- Packages with network permissions
- Packages not updated in >1 year
8. Native Code Security (HIGH)
iOS - Check Info.plist:
# Find Info.plist
find . -name "Info.plist" -exec echo "=== {} ===" \; -exec cat {} \;
# Check for insecure settings
grep -E "(NSAllowsArbitraryLoads|NSExceptionDomains|NSAppTransportSecurity)" ios/*/Info.plist
Android - Check AndroidManifest.xml:
# Find manifests
find . -name "AndroidManifest.xml" -exec echo "=== {} ===" \; -exec cat {} \;
# Check permissions
grep -E "(permission|uses-permission)" android/app/src/main/AndroidManifest.xml
# Check for backup enabled (data extraction risk)
grep -E "android:allowBackup" android/app/src/main/AndroidManifest.xml
# Check for debuggable
grep -E "android:debuggable" android/app/src/main/AndroidManifest.xml
# Check exported components
grep -E "android:exported" android/app/src/main/AndroidManifest.xml
Dangerous Android permissions:
<!-- Review if truly needed -->
READ_CONTACTS, WRITE_CONTACTS
READ_CALL_LOG, WRITE_CALL_LOG
READ_SMS, SEND_SMS
ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION
CAMERA, RECORD_AUDIO
READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE
Automated Scanning
Run All Checks Script
#!/bin/bash
# rn-security-scan.sh
OUTPUT_DIR="./security-audit-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"
echo "=== React Native Security Scan ===" | tee "$OUTPUT_DIR/report.txt"
echo -e "\n[1/8] Scanning for hardcoded secrets..." | tee -a "$OUTPUT_DIR/report.txt"
grep -rniE "(api[_-]?key|api[_-]?secret|access[_-]?token|auth[_-]?token|private[_-]?key|secret[_-]?key)\s*[:=]\s*['\"][a-zA-Z0-9]" \
--include="*.js" --include="*.ts" --include="*.tsx" --include="*.json" . 2>/dev/null | \
grep -v node_modules | grep -v ".lock" > "$OUTPUT_DIR/secrets.txt"
echo "Found $(wc -l < "$OUTPUT_DIR/secrets.txt") potential secrets"
echo -e "\n[2/8] Scanning for AWS credentials..." | tee -a "$OUTPUT_DIR/report.txt"
grep -rniE "(AKIA|ASIA)[A-Z0-9]{16}" --include="*.js" --include="*.ts" --include="*.json" . 2>/dev/null | \
grep -v node_modules > "$OUTPUT_DIR/aws-keys.txt"
echo "Found $(wc -l < "$OUTPUT_DIR/aws-keys.txt") potential AWS keys"
echo -e "\n[3/8] Scanning for insecure HTTP..." | tee -a "$OUTPUT_DIR/report.txt"
grep -rniE "http://(?!localhost|127\.0\.0\.1|10\.|192\.168\.)" \
--include="*.js" --include="*.ts" --include="*.json" . 2>/dev/null | \
grep -v node_modules > "$OUTPUT_DIR/insecure-http.txt"
echo "Found $(wc -l < "$OUTPUT_DIR/insecure-http.txt") insecure HTTP URLs"
echo -e "\n[4/8] Scanning for AsyncStorage with sensitive data..." | tee -a "$OUTPUT_DIR/report.txt"
grep -rniE "AsyncStorage" --include="*.js" --include="*.ts" . 2>/dev/null | \
grep -iE "(token|password|secret|key|auth|credential)" | \
grep -v node_modules > "$OUTPUT_DIR/async-storage.txt"
echo "Found $(wc -l < "$OUTPUT_DIR/async-storage.txt") AsyncStorage concerns"
echo -e "\n[5/8] Scanning for console.log with sensitive data..." | tee -a "$OUTPUT_DIR/report.txt"
grep -rniE "console\.(log|debug|info)\s*\([^)]*?(password|token|secret|key|credential|auth)" \
--include="*.js" --include="*.ts" --include="*.tsx" . 2>/dev/null | \
grep -v node_modules > "$OUTPUT_DIR/console-leaks.txt"
echo "Found $(wc -l < "$OUTPUT_DIR/console-leaks.txt") console logging concerns"
echo -e "\n[6/8] Scanning for eval() usage..." | tee -a "$OUTPUT_DIR/report.txt"
grep -rniE "\beval\s*\(" --include="*.js" --include="*.ts" . 2>/dev/null | \
grep -v node_modules > "$OUTPUT_DIR/eval-usage.txt"
echo "Found $(wc -l < "$OUTPUT_DIR/eval-usage.txt") eval() usages"
echo -e "\n[7/8] Running npm audit..." | tee -a "$OUTPUT_DIR/report.txt"
npm audit --json 2>/dev/null > "$OUTPUT_DIR/npm-audit.json"
echo "NPM audit complete"
echo -e "\n[8/8] Checking native configs..." | tee -a "$OUTPUT_DIR/report.txt"
grep -E "NSAllowsArbitraryLoads|android:allowBackup.*true|android:debuggable.*true" \
ios/*/Info.plist android/app/src/main/AndroidManifest.xml 2>/dev/null > "$OUTPUT_DIR/native-config.txt"
echo "Found $(wc -l < "$OUTPUT_DIR/native-config.txt") native config concerns"
echo -e "\n=== Scan Complete ===" | tee -a "$OUTPUT_DIR/report.txt"
echo "Results saved to $OUTPUT_DIR"
Using External Tools
# MobSF (Mobile Security Framework)
docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf
# Semgrep for React Native
semgrep --config=p/react-native .
# GitLeaks for secret scanning
gitleaks detect --source=. --report-path=gitleaks-report.json
# Trivy for dependency scanning
trivy fs --security-checks vuln,secret .
Security Checklist
Pre-Release Audit
| Category | Check | Severity |
|---|---|---|
| Secrets | No hardcoded API keys | CRITICAL |
| Secrets | No credentials in code | CRITICAL |
| Secrets | .env files in .gitignore | CRITICAL |
| Storage | Tokens in Keychain/Keystore | HIGH |
| Storage | No PII in AsyncStorage | HIGH |
| Network | All endpoints HTTPS | HIGH |
| Network | Certificate pinning enabled | MEDIUM |
| Auth | Tokens not logged | HIGH |
| Auth | Secure token refresh flow | HIGH |
| Auth | Biometrics properly implemented | MEDIUM |
| Logging | No sensitive data in logs | HIGH |
| Logging | Console.log stripped in prod | MEDIUM |
| Native | allowBackup=false (Android) | HIGH |
| Native | debuggable=false (Android) | HIGH |
| Native | ATS enabled (iOS) | MEDIUM |
| Deps | No critical npm vulnerabilities | HIGH |
| Deps | Dependencies up to date | MEDIUM |
| Code | No eval() usage | MEDIUM |
| Code | Input validation on deep links | MEDIUM |
| Code | WebView injection prevented | MEDIUM |
OWASP MASVS Mapping
| MASVS Category | This Skill Covers |
|---|---|
| V1: Architecture | Deep link validation, component security |
| V2: Data Storage | AsyncStorage, Keychain, encrypted storage |
| V3: Cryptography | Secure random, key storage |
| V4: Authentication | Token handling, biometrics, session |
| V5: Network | HTTPS, cert pinning, SSL verification |
| V6: Platform | Native permissions, manifest security |
| V7: Code Quality | Logging, debugging, input validation |
| V8: Resilience | Obfuscation checks, anti-tampering |
Severity Reference
| Level | Description | Action |
|---|---|---|
| CRITICAL | Immediate exploitation risk, data breach | Fix before any release |
| HIGH | Significant security risk | Fix before production |
| MEDIUM | Defense-in-depth issue | Fix in next sprint |
| LOW | Minor issue, best practice | Track in backlog |
More from johanruttens/paddle-battle
apple-app-store-agent
Comprehensive agent for preparing and generating all assets needed for Apple App Store submission. Use when user needs to prepare an iOS/iPadOS/macOS app for App Store release, including generating app metadata (descriptions, promotional text, keywords), creating app icons, designing screenshots, preparing privacy policy URLs, and organizing fastlane-compatible folder structures. Triggers on requests like "prepare my app for App Store", "create App Store screenshots", "generate app description", "make app icon", or "set up fastlane metadata".
9game-developer
Expert game development and design skill for building complete, polished games. Use when creating games, game prototypes, or interactive entertainment experiences across platforms (React Native, web, Unity concepts, Godot). Covers game mechanics, physics, AI opponents, level design, progression systems, visual effects, sound integration, and player experience. Triggers on requests to build games, create game mechanics, design levels, implement game AI, add game audio, or develop interactive entertainment.
8skill-writer
Guide users through creating Agent Skills for Claude Code. Use when the user wants to create, write, author, or design a new Skill, or needs help with SKILL.md files, frontmatter, or skill structure.
5react-native-expert
Expert guidance for building mobile applications with React Native and Expo. Use when the user asks to create, modify, debug, or architect mobile apps, implement native features (camera, notifications, storage, navigation), set up React Native projects, work with Expo or bare React Native workflows, integrate with device APIs, handle app state management, or optimize mobile performance. Triggers on mobile app development, React Native, Expo, iOS/Android cross-platform development.
5qa-engineer
Expert guidance for software testing and quality assurance. Use when the user asks to write tests, create test plans, review code for bugs, perform code reviews, write test cases, set up testing frameworks, debug issues, validate requirements, create bug reports, perform regression testing, or improve test coverage. Triggers on testing, QA, quality assurance, test cases, bug reports, test automation, unit tests, integration tests, E2E tests, test coverage, debugging, code review.
4rn-visual-testing
Visual testing skill for React Native apps across iPhone models. Use when testing app appearance on iPhone 11 through 17 (all variants including Pro, Pro Max, Plus, Mini, Air, and SE). Covers screenshot capture, simulator configuration, screen dimension validation, safe area handling, Dynamic Island/notch compatibility, and pixel-perfect verification across all iPhone screen sizes and resolutions.
4