{"id":29023039,"url":"https://github.com/bamlab/react-native-app-security","last_synced_at":"2025-06-26T03:05:12.334Z","repository":{"id":212131613,"uuid":"725205532","full_name":"bamlab/react-native-app-security","owner":"bamlab","description":"Easily implement usual security measures in React Native Expo apps. Made by BAM ❤️💙💛","archived":false,"fork":false,"pushed_at":"2025-04-18T10:12:34.000Z","size":959,"stargazers_count":105,"open_issues_count":4,"forks_count":4,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-07T09:12:35.577Z","etag":null,"topics":["expo","react-native","security","ssl-pinning"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bamlab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-11-29T16:50:41.000Z","updated_at":"2025-05-04T16:30:51.000Z","dependencies_parsed_at":"2023-12-20T08:00:25.844Z","dependency_job_id":"252cd3ee-31de-4677-ab3a-d4d26ad77bac","html_url":"https://github.com/bamlab/react-native-app-security","commit_stats":{"total_commits":29,"total_committers":6,"mean_commits":4.833333333333333,"dds":"0.24137931034482762","last_synced_commit":"33d8bfa55b76b7f6d2f5cc4c57e3b2bb391650ee"},"previous_names":["bamlab/react-native-app-security"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/bamlab/react-native-app-security","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bamlab%2Freact-native-app-security","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bamlab%2Freact-native-app-security/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bamlab%2Freact-native-app-security/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bamlab%2Freact-native-app-security/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bamlab","download_url":"https://codeload.github.com/bamlab/react-native-app-security/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bamlab%2Freact-native-app-security/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261990349,"owners_count":23241188,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expo","react-native","security","ssl-pinning"],"created_at":"2025-06-26T03:05:11.819Z","updated_at":"2025-06-26T03:05:12.315Z","avatar_url":"https://github.com/bamlab.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ereact-native-app-security 🔐\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eEasily implement usual security measures in React Native Expo apps\u003c/p\u003e\n\n- [Installation and setup](#installation-and-setup)\n- [Features](#features)\n  - [SSL Pinning](#ssl-pinning)\n    - [Configuration](#configuration)\n      - [Pinning subdomains](#pinning-subdomains)\n    - [Generating the public key hashes](#generating-the-public-key-hashes)\n    - [Testing](#testing)\n  - [Certificate transparency](#certificate-transparency)\n    - [Configuration](#configuration-1)\n  - [Prevent \"recent screenshots\"](#prevent-recent-screenshots)\n    - [Configuration](#configuration-2)\n  - [Safe Keyboard Detector](#safe-keyboard-detector)\n- [Contributing](#contributing)\n- [👉 About BAM](#-about-bam)\n\n\u003e **⚠️ Disclaimer**\u003cbr/\u003e\n\u003e This package is intended to help implement a few basic security features but does not in itself guarantee that an app is secure.\u003cbr/\u003e\n\u003e Refer to [OWASP's resources](https://mas.owasp.org) for more information on mobile app security.\u003cbr/\u003e\n\u003e You can also [contact us](https://www.bam.tech/en/contact) if you need help with securing your app.\n\n# Installation and setup\n\nThis package is designed for use in expo apps with [development builds](https://docs.expo.dev/develop/development-builds/introduction/).\n\n```sh\nyarn add @bam.tech/react-native-app-security\n```\n\nAdd the config plugin to `app.config.ts` / `app.config.js` / `app.json`:\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@bam.tech/react-native-app-security\",\n      {\n        \"sslPinning\": {\n          \"yahoo.com\": [\n            \"TQEtdMbmwFgYUifM4LDF+xgEtd0z69mPGmkp014d6ZY=\",\n            \"rFjc3wG7lTZe43zeYTvPq8k4xdDEutCmIhI5dn4oCeE=\"\n          ]\n        },\n        \"preventRecentScreenshots\": {\n          \"ios\": { \"enabled\": true },\n          \"android\": { \"enabled\": true }\n        }\n      }\n    ]\n  ]\n}\n```\n\nAnytime you change the config, don't forget to run:\n\n```sh\nyarn expo prebuild\n```\n\n# Features\n\n## SSL Pinning\n\n\u003e **🥷 What's the threat?** Attackers intercepting your app's network requests and accessing private data or sending malicious responses. [More details](https://github.com/OWASP/owasp-mastg/blob/master/Document/0x04f-Testing-Network-Communication.md#restricting-trust-identity-pinning)\n\nThis package implements [public key pinning](https://cheatsheetseries.owasp.org/cheatsheets/Pinning_Cheat_Sheet.html#public-key) using [TrustKit](https://github.com/datatheorem/TrustKit) on iOS and the certificate pinner included in OkHttp on Android.\n\n### Configuration\n\n```jsonc\n[\n  \"@bam.tech/react-native-app-security\",\n  {\n    \"sslPinning\": {\n      // The hostname you want to pin, without `https://`\n      \"yahoo.com\": [\n        // The public key hashes for the pinned certificates, without a `sha256/` prefix\n        \"TQEtdMbmwFgYUifM4LDF+xgEtd0z69mPGmkp014d6ZY=\",\n        \"rFjc3wG7lTZe43zeYTvPq8k4xdDEutCmIhI5dn4oCeE=\"\n      ]\n    }\n  }\n]\n```\n\nPlease note that you'll need to provide _2_ public key hashes. This is to encourage having proper procedures in place to avoid locking users out, [as described here in the TrustKit docs](https://github.com/datatheorem/TrustKit/blob/master/docs/getting-started.md#always-provide-at-least-one-backup-pin).\n\n#### Pinning subdomains\n\nTo pin a specific subdomain, simply include it in the string you provide, eg:\n\n```jsonc\n    \"sslPinning\": {\n      \"subdomain.domain.com\": [/* ... */]\n    }\n```\n\nTo pin a domain and all its subdomains, use a wildcard:\n\n```jsonc\n    \"sslPinning\": {\n      // domain.com and all its subdomains will be pinned\n      \"*.domain.com\": [/* ... */]\n    }\n```\n\n\u003e The wildcard can only be used for the full lefmost part of the hostname.\n\u003e\n\u003e These are invalid: `*domain.com`, `domain.*.com`, `sub.*.domain.com`\n\n### Generating the public key hashes\n\nYou'll need the certificates (`.cer` or `.crt`)\n\n```sh\nopenssl x509 -in certificate.cer -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64\n```\n\n### Testing\n\nTo test that SSL pinning is working as expected, you can:\n\n- break (change) a certificate and check that the connection fails _(don't forget to `yarn expo prebuild` then `yarn ios` or `yarn android` to rebuild the app)_\n- set up a proxy (we love [Proxyman](https://proxyman.io)) and check that the connection fails\n\n## Certificate transparency\n\n\u003e **🥷 What's the threat?** Compromised certificate authorities. [More details](https://certificate.transparency.dev)\n\n- On iOS, [certificate transparency is enabled by default](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-12_1_1-release-notes) since _iOS 12.1.1_\n- On Android, this package enables it using [appmatus/certificatetransparency](https://github.com/appmattus/certificatetransparency) for _Android \u003e= 8.0_\n\n### Configuration\n\nNone, enabled by default.\n\n## Prevent \"recent screenshots\"\n\n\u003e **🥷 What's the threat?** When the OS terminates the app, it may take a screenshot and store it on the device to display in the app switcher. This screenshot could leak sensitive data\n\nMitigating this threat is achieved by:\n\n- Using [`FLAG_SECURE`](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_SECURE) on Android \u003c 13\n- Using [`Activity.setRecentScreenshotsEnabled`](\u003chttps://developer.android.com/reference/android/app/Activity#setRecentsScreenshotEnabled(boolean)\u003e) on Android \u003e= 13\n- Covering the app with the splashscreen on iOS (requires [expo-splash-screen](https://docs.expo.dev/versions/latest/sdk/splash-screen/) to be setup)\n\n### Configuration\n\n```jsonc\n[\n  \"@bam.tech/react-native-app-security\",\n  {\n    \"preventRecentScreenshots\": {\n      \"ios\": { \"enabled\": true },\n      \"android\": { \"enabled\": true }\n    }\n  }\n]\n```\n\n## Safe Keyboard Detector\n\n\u003e **🥷 What's the threat?** A third-party keyboard might embed a malicious keylogger to record passwords and sensitive data. [More details](https://www.synopsys.com/blogs/software-security/mitigate-third-party-mobile-keyboard-risk.html)\n\nMitigating this threat is achieved by:\n\n- On Android, comparing the current keyboard id with a list of [keyboard packages that we deem safe](./android/src/main/java/tech/bam/rnas/RNASModule.kt#31).\n- On iOS, doing nothing specific since iOS already prevent the use of third-party keyboard on sensitive fields such as passwords.\n\n```tsx\nimport { SafeKeyboardDetector } from \"@bam.tech/react-native-app-security\";\n\nconst { isInDefaultSafeList, inputMethodId } = getCurrentInputMethodInfo(); // Will always return {isInDefaultSafeList: true, inputMethodId: \"iosKeyboard\"} on iOS\nif (!isInDefaultSafeList) {\n  console.warn(`Your current keyboard (${inputMethodId}) is not safe`);\n}\n\n// Prompt the user to change the current keyboard\nSafeKeyboardDetector.showInputMethodPicker(); // can only be called on Android\n```\n\n# Contributing\n\nContributions are welcome. See the [Expo modules docs](https://docs.expo.dev/modules/get-started/) for information on how to build/run/develop on the project.\n\nWhen making a change to the `plugin` folder, you'll need to run `yarn prepare` before prebuilding and building the example app.\n\n# 👉 About BAM\n\nWe are a 100 people company developing and designing multi-platform applications with [React Native](https://www.bam.tech/expertise/react-native) using the Lean \u0026 Agile methodology. To get more information on the solutions that would suit your needs, feel free to get in touch by [email](mailto:contact@bam.tech) or through our [contact form](https://www.bam.tech/en/contact)!\n\nWe will always answer you with pleasure 😁\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbamlab%2Freact-native-app-security","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbamlab%2Freact-native-app-security","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbamlab%2Freact-native-app-security/lists"}