rn-security-audit

📁 johanruttens/paddle-battle 📅 Jan 25, 2026
0
总安装量
2
周安装量
安装命令
npx skills add https://github.com/johanruttens/paddle-battle --skill rn-security-audit

Agent 安装分布

opencode 2
gemini-cli 2
antigravity 2
windsurf 2
codex 2

Skill 文档

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