npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@think-grid-labs/react-native-shield

v0.4.1

Published

React Native security library — root detection, jailbreak detection, SSL pinning, biometric authentication, secure storage, and Play Integrity attestation for iOS and Android

Downloads

156

Readme

react-native-shield — React Native Security Suite

The All-in-One Security Suite for React Native.

npm version License: MIT

react-native-shield provides a unified, easy-to-use API for essential mobile security features. Instead of managing multiple fragmented libraries for SSL pinning, root detection, secure storage, and UI privacy, you get a single TurboModule package that "just works" on both Android and iOS.

Features

  • ✅ Device Integrity — Detect if a device is Rooted (Android) or Jailbroken (iOS), with detailed reason codes.
  • 🕵️ Anti-Tampering — Detect Emulator/Simulator, attached Debugger, hooking frameworks (Frida/Xposed), and developer mode.
  • 🔐 Platform Attestation — Request a cryptographically signed integrity token from Google (Play Integrity API) or Apple (DeviceCheck) for server-side verification.
  • 🔒 SSL Pinning — Secure your network requests against Man-in-the-Middle (MitM) attacks by pinning your server's public key hash.
  • 🔑 Secure Storage — Store sensitive tokens in the device's secure hardware (Keychain on iOS, EncryptedSharedPreferences on Android), with full key enumeration and bulk wipe.
  • 🤝 Biometric Authentication — Native biometric prompt (Face ID / Touch ID / Android Biometrics) with strength-level awareness.
  • 👁️ UI Privacy — Prevent screenshots and screen recording. Automatically blur app content when backgrounded.
  • ⚡ TurboModule API — Built on the New Architecture (TurboModules) for synchronous access and optimal performance.

Installation

npm install @think-grid-labs/react-native-shield
# or
yarn add @think-grid-labs/react-native-shield
# or
pnpm add @think-grid-labs/react-native-shield

iOS Setup

The iOS implementation relies on TrustKit for SSL pinning and links DeviceCheck for attestation. Install CocoaPods dependencies:

cd ios && pod install

Android Setup

No extra steps needed. Play Integrity (com.google.android.play:integrity) is bundled automatically.


Modules & Usage

import {
  isRooted,
  isEmulator,
  isDebuggerAttached,
  verifySignature,
  isHooked,
  isDeveloperModeEnabled,
  isVPNDetected,
  getRootReasons,
  protectClipboard,
  authenticateWithBiometrics,
  getBiometricStrength,
  addSSLPinning,
  updateSSLPins,
  preventScreenshot,
  setSecureString,
  getSecureString,
  removeSecureString,
  getAllSecureKeys,
  clearAllSecureStorage,
  requestIntegrityToken,
} from '@think-grid-labs/react-native-shield';

1. Device Integrity & Anti-Tampering

Check if the device environment is safe. All checks are synchronous TurboModule calls for immediate, blocking results — safe to use before any sensitive operation.

const checkIntegrity = () => {
  if (isRooted()) {
    console.warn('Security Alert: Device is rooted or jailbroken.');
    // Block sensitive actions, wipe session tokens, or alert the user.
  }

  if (isEmulator()) {
    console.warn('Security Alert: App is running in an emulator.');
    // Reject automated testing environments in production builds.
  }

  if (isDebuggerAttached()) {
    console.warn('Security Alert: Debugger attached.');
    // Halt execution to prevent runtime inspection of secrets.
  }

  if (isDeveloperModeEnabled()) {
    console.warn('Security Alert: ADB/Developer Mode is enabled (Android).');
  }

  if (isHooked()) {
    console.warn('Security Alert: Injection framework detected (Frida/Xposed).');
    // Terminate the session — the runtime may be instrumented.
  }

  if (!verifySignature('YOUR_EXPECTED_SHA256_HASH')) {
    console.warn('Security Alert: App signature mismatch — possible repackaging.');
    // The APK may have been modified and redistributed. Refuse to run.
  }
};

Root / Jailbreak Reason Codes

Instead of a plain boolean, get a list of why the device is flagged — useful for risk scoring, logging, or tuning sensitivity per environment.

const reasons = getRootReasons();
// Android example: ['su_binary', 'dangerous_packages']
// iOS example:     ['jailbreak_files', 'sandbox_escape']

if (reasons.length > 0) {
  // Send reasons to your security analytics backend
  reportThreat({ reasons, platform: Platform.OS });
}

Possible reason codes:

| Code | Platform | Meaning | |---|---|---| | build_tags | Android | Build.TAGS contains test-keys | | su_binary | Android | su binary found in common paths | | su_command | Android | which su command succeeded | | dangerous_packages | Android | Known root manager apps installed (Magisk, SuperSU, etc.) | | mount_flags | Android | /system partition mounted read-write | | jailbreak_files | iOS | Cydia, Sileo, Zebra, MobileSubstrate, bash, sshd found | | sandbox_escape | iOS | Write outside sandbox succeeded | | cydia_scheme | iOS | cydia:// URL scheme is openable | | substrate_loaded | iOS | MobileSubstrate/Substrate dylib loaded into the process |

Use cases:

  • Banking / fintech apps — block transactions when su_binary or sandbox_escape is present.
  • DRM-protected content — deny playback on devices with dangerous_packages.
  • Risk-adaptive UX — show a security warning without fully blocking when only build_tags is set (mild signal).

Implementation Details:

| Check | Android | iOS | |---|---|---| | Root | Build.TAGS, su binary scan, which su, known root package names, /proc/mounts flags | Jailbreak files, sandbox write test, Cydia URL scheme, dyld substrate scan | | Emulator | Build.FINGERPRINT/MODEL/HARDWARE/PRODUCT patterns | TARGET_OS_SIMULATOR compile-time macro | | Debugger | android.os.Debug.isDebuggerConnected() | sysctl P_TRACED flag | | Signature | SHA-256 of PackageManager signing certs | Presence of embedded.mobileprovision | | Hooking | ClassLoader probe (Xposed/Substrate), frida-server file | dyld image name scan (Frida, Substrate, cycript, SSLKillSwitch) | | Dev mode | Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, ADB_ENABLED | Not supported (always false) |


2. Platform Attestation

Request a cryptographically signed integrity token from Google or Apple that your server can verify. This is the only mechanism that provides hardware-backed, unforgeable proof of device and app integrity — something no local detection heuristic can match.

// Call from your login or session-start flow.
// The nonce must be generated server-side (unique, unpredictable).
const verifyDeviceWithServer = async () => {
  try {
    const nonce = await fetchNonceFromServer(); // your API
    const token = await requestIntegrityToken(nonce);

    // Send token to your backend for verification
    await sendToBackend({ token, platform: Platform.OS });
    // Android: verify via Google Play Integrity API
    // iOS: verify via Apple DeviceCheck API
  } catch (e) {
    // 'INTEGRITY_NOT_SUPPORTED' — emulator or unsigned build
    // 'INTEGRITY_ERROR' — network or Play Services unavailable
    console.error('Attestation failed:', e);
  }
};

Platform behavior:

  • Android — Uses Play Integrity API. The returned token encodes: appIntegrity (cert match + install source), deviceIntegrity (hardware attestation), and accountDetails (licensed via Play). Verify server-side with https://playintegrity.googleapis.com.
  • iOS — Uses DeviceCheck. The returned token is a base64-encoded device attestation verifiable via Apple's DeviceCheck servers.

Use cases:

  • Prevent API abuse — only honor requests from genuine, unmodified app installs.
  • Anti-bot for login flows — rate-limit or block attestation failures.
  • High-value transactions — require a fresh attestation token before wire transfers or crypto withdrawals.
  • License enforcement — confirm the app was installed from the official store, not sideloaded.

Note: The nonce should be a server-generated, single-use random value (minimum 16 bytes, base64-encoded). Reusing nonces defeats replay protection.


3. App Environment Security

const protectAppEnvironment = () => {
  if (isVPNDetected()) {
    console.warn('Network path is routed through a VPN or proxy.');
    // Optionally warn users that certificate pinning may behave differently,
    // or block access to sensitive features in high-security contexts.
  }

  // Auto-clear clipboard whenever the app backgrounds
  protectClipboard(true);
};

Use cases:

  • Compliance apps — some regulated environments prohibit VPN usage on managed devices.
  • Clipboard protection — prevent a copied password or OTP from persisting after the user leaves the app (banking, password managers).

4. Biometric Authentication

Authenticate the user

const loginWithBiometrics = async () => {
  const success = await authenticateWithBiometrics('Authenticate to continue');
  if (success) {
    // Unlock secure vault, proceed to dashboard, etc.
  } else {
    // User cancelled or biometric not matched — show fallback UI
  }
};

Check biometric strength before gating features

Different biometric sensors have very different security properties. Face Unlock on Android is classified as "weak" (2D camera, spoofable with a photo). Face ID on iOS and fingerprint readers are "strong" (secure enclave, spoof-resistant hardware).

const enforceStrongBiometrics = async () => {
  const strength = await getBiometricStrength();
  // Returns: "strong" | "weak" | "none"

  if (strength === 'strong') {
    // Unlock cryptographic keys, allow high-value operations
  } else if (strength === 'weak') {
    // Allow login but require step-up auth for sensitive actions
    console.warn('Biometric strength is weak — consider requiring a PIN for payments.');
  } else {
    // No biometrics enrolled — fall back to password/PIN
  }
};

Use cases:

  • Tiered access control — only allow "strong" biometrics to authorize payments or PII access; "weak" for general app unlock.
  • FIDO2 / passkey flows — gate passkey creation on "strong" hardware.
  • Adaptive security UI — surface a warning banner if only weak biometrics are available.

5. SSL / Certificate Pinning

Prevent MitM attacks by verifying that your server's certificate public key matches your predefined pins.

// Call EARLY in your app lifecycle (e.g., App.tsx root useEffect or index.js).
useEffect(() => {
  const configurePinning = async () => {
    try {
      await addSSLPinning('api.yourdomain.com', [
        'sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=', // Primary pin
        'sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB='  // Backup pin
      ]);
    } catch (e) {
      console.error('SSL pinning failed:', e);
    }
  };
  configurePinning();
}, []);

Rotating pins (Android only):

On Android, OkHttp allows the client factory to be replaced at runtime, so updateSSLPins takes effect immediately. On iOS, TrustKit locks its configuration at startup — updateSSLPins will reject with SSL_PIN_UPDATE_UNSUPPORTED. To rotate iOS pins, update addSSLPinning arguments and ship an app update (or restart).

// Android: works at runtime
// iOS: throws SSL_PIN_UPDATE_UNSUPPORTED — catch it!
try {
  await updateSSLPins('api.yourdomain.com', [
    'sha256/CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC='
  ]);
} catch (e: any) {
  if (e.code === 'SSL_PIN_UPDATE_UNSUPPORTED') {
    // Expected on iOS — handled. New pins take effect after next app launch.
  }
}

How to extract your pin hash:

openssl s_client -servername api.yourdomain.com -connect api.yourdomain.com:443 \
  | openssl x509 -pubkey -noout \
  | openssl pkey -pubin -outform der \
  | openssl dgst -sha256 -binary \
  | openssl enc -base64

Use cases:

  • Fintech / healthcare — mandatory in PCI-DSS and HIPAA environments to prevent intercepted API calls.
  • Auth token endpoints — pin only your /token and /refresh endpoints to limit blast radius.
  • Always provide a backup pin — a single pin + certificate expiry = production outage. Always include at least one backup.

6. Secure Storage

Store secrets (tokens, API keys, encryption keys) in the device's hardware-backed secure enclave.

// Save
await setSecureString('access_token', 'eyJhbGci...');

// Read
const token = await getSecureString('access_token'); // string | null

// Delete one key
await removeSecureString('access_token');

Enumerate and audit stored keys

const keys = await getAllSecureKeys();
// e.g. ['access_token', 'refresh_token', 'user_id']

// Useful for: migration scripts, key rotation, debugging storage state
console.log('Stored keys:', keys);

Bulk wipe on logout or account deletion

const handleLogout = async () => {
  await clearAllSecureStorage();
  // All keys under this app's bundle ID are gone.
  // Safe to call even if storage is already empty.
};

Implementation Details:

  • AndroidEncryptedSharedPreferences with AES256-GCM, backed by Android Keystore master key.
  • iOS — Keychain Services (SecItemAdd / SecItemCopyMatching) scoped to the app's bundle ID.

Use cases:

  • setSecureString / getSecureString — persist OAuth tokens, refresh tokens, or biometric-bound keys.
  • getAllSecureKeys — audit what's in storage before a migration; compare against an expected key manifest.
  • clearAllSecureStorage — GDPR "right to erasure" flows, account deletion, forced logout on session invalidation.

7. UI Privacy

Prevent sensitive UI from being captured in screenshots, screen recordings, or the OS app switcher preview.

// Enable — call once at app startup or when entering a sensitive screen
await preventScreenshot(true);

// Disable — call when leaving the sensitive context
await preventScreenshot(false);

Use cases:

  • Banking / wallet apps — enable on balance screens, transaction history, and transfer confirmations.
  • Password managers — enable globally; users won't be able to screenshot their vault.
  • Healthcare — prevent patient data from appearing in OS recent-apps thumbnails.
  • Chat apps with disappearing messages — enable on message screens to block screen recording.

Platform Behavior:

| | Android | iOS | |---|---|---| | Screenshot | Blocked via FLAG_SECURE | Not blockable (OS limitation) | | Screen recording | Blocked via FLAG_SECURE | Content masked via UITextField.secureTextEntry layer hack | | App switcher preview | Replaced with blank screen | Blur overlay injected on WillResignActive |

⚠️ iOS limitation: Hardware screenshots (Home + Power) cannot be blocked by any third-party app on iOS. preventScreenshot primarily protects against screen recording, AirPlay mirroring, and the app switcher preview.


API Reference

Device Integrity

| Method | Returns | Description | |---|---|---| | isRooted() | boolean | true if device is rooted (Android) or jailbroken (iOS) | | isEmulator() | boolean | true if running in a simulator or emulator | | isDebuggerAttached() | boolean | true if a debugger is attached to the process | | isDeveloperModeEnabled() | boolean | true if ADB/developer options are active (Android only) | | isHooked() | boolean | true if Frida, Xposed, Substrate, or similar is detected | | verifySignature(hash) | boolean | true if the app's signing cert matches the expected hash | | getRootReasons() | string[] | Array of reason codes explaining why the device is flagged |

Network & Environment

| Method | Returns | Description | |---|---|---| | isVPNDetected() | boolean | true if traffic is routed through a VPN interface | | protectClipboard(protect) | Promise<void> | Toggle auto-clear clipboard on app background |

Platform Attestation

| Method | Returns | Description | |---|---|---| | requestIntegrityToken(nonce) | Promise<string> | Play Integrity token (Android) or DeviceCheck token (iOS) for server-side verification |

Biometrics

| Method | Returns | Description | |---|---|---| | authenticateWithBiometrics(prompt) | Promise<boolean> | Launches native biometric prompt; resolves true on success | | getBiometricStrength() | Promise<string> | "strong", "weak", or "none" based on enrolled biometric hardware |

SSL Pinning

| Method | Returns | Description | |---|---|---| | addSSLPinning(domain, hashes) | Promise<void> | Enable certificate pinning for a domain | | updateSSLPins(domain, hashes) | Promise<void> | Update pins at runtime (Android only; rejects with SSL_PIN_UPDATE_UNSUPPORTED on iOS) |

Secure Storage

| Method | Returns | Description | |---|---|---| | setSecureString(key, value) | Promise<boolean> | Encrypt and store a string | | getSecureString(key) | Promise<string \| null> | Decrypt and retrieve a stored string | | removeSecureString(key) | Promise<boolean> | Delete a single key from secure storage | | getAllSecureKeys() | Promise<string[]> | List all keys currently in secure storage | | clearAllSecureStorage() | Promise<boolean> | Delete all keys from secure storage |

UI Privacy

| Method | Returns | Description | |---|---|---| | preventScreenshot(prevent) | Promise<void> | Toggle screenshot/recording prevention and background blur |


Security Architecture Overview

┌─────────────────────────────────────────────────────────┐
│                   react-native-shield                   │
├───────────────┬──────────────────┬──────────────────────┤
│ Device Check  │  Network Layer   │    Data Layer        │
│               │                  │                      │
│ isRooted()    │ addSSLPinning()  │ setSecureString()    │
│ isEmulator()  │ updateSSLPins()  │ getSecureString()    │
│ isHooked()    │ isVPNDetected()  │ removeSecureString() │
│ getRootReasons│                  │ getAllSecureKeys()    │
│               │  Attestation     │ clearAllSecureStorage│
│ isDebugger    │                  │                      │
│ Attached()    │ requestIntegrity │    UI Layer          │
│ verifySigna-  │ Token()          │                      │
│ ture()        │                  │ preventScreenshot()  │
│               │  Biometrics      │ protectClipboard()   │
│               │                  │                      │
│               │ authenticateWith │                      │
│               │ Biometrics()     │                      │
│               │ getBiometric     │                      │
│               │ Strength()       │                      │
└───────────────┴──────────────────┴──────────────────────┘
         ↓                  ↓                   ↓
    Android/iOS        OkHttp /           Keystore /
    System APIs        TrustKit           Keychain
                    Play Integrity /
                      DeviceCheck

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT