Skip to content

Commit

Permalink
feat: add SES to wallet-mobile (#420)
Browse files Browse the repository at this point in the history
* refactor: feature toggle using hathor unleash client

* feat: handling feature updates

* feat: added SES to the project and enabled lockdown

* chore: added patch-package and patch to react-native

* chore: removed unused diff from react-native patch

* chore: added allow-scripts

* chore: added updated allowScript config

* chore: added sha256sum of lockdown file

* refactor: moved lavamoat lockdown to a patch instead of entrypoint

* refactor: removed ses from package.json, reading from file

* chore: fix lint by ignoring lockdown

* chore: allowing root postinstall and running allow-scripts on npm run setup

* chore: added comment explaining why we can't use hermes

* chore: uninstall ses as we're using a downloaded file

* chore: removed unused diff from react-native patch

* chore: no need to remove polyfill promise as injecting it on initializeCore fixes the issue

* chore: updated react-native patch to include react-native-mmkv and use it

* feat: added ses saga and restarting bundle when ses is disabled

* chore: added a document explaining how to update SES

* chore: added postinstall to setup script and updated packages

* chore: fixed allow-scripts version

* chore: added patch-package to postinstall

* chore: added MKMV to podfile.lock

* chore: reading ses enabled from constant

* feat: yield fatal error when SES should be enabled but is not

* refactor: improved verifySesEnabled method

* feat: update SES to 1.5.0

* feat: patched intl to work in SES

* refactor: updated react-native patch import order

* feat: improved logging and updated podfile with sentry update and mmkv

* fix: typo

* docs: improved comment on unleash disabled

* refactor: use isSESEnabled

* chore: updated sha256sums

* docs: updated SES_AND_LAVAMOAT document with better explanation on SES

* refactor: disabled hermes on android

* refactor: updated react-native patch, removed unused changes

* refactor: updated intl patch to remove unused implementation

* chore: added comment on react-native patch

* chore: removed exit 1 from preinstall on root

* chore: updated intl patch to add a comment

* fix: updated translation files

* chore: remove unused actions, reducer and saga effect

---------

Co-authored-by: Alex Ruzenhack <[email protected]>
  • Loading branch information
andreabadesso and alexruzenhack authored Nov 7, 2024
1 parent eb36418 commit 2a65bf2
Show file tree
Hide file tree
Showing 24 changed files with 13,963 additions and 368 deletions.
1 change: 1 addition & 0 deletions .babelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lockdown.umd.js
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "airbnb",
"parser": "@babel/eslint-parser",
"ignorePatterns": ["lockdown.umd.js"],
"plugins": [
"react"
],
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore-scripts=true
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lockdown.umd.js
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ See the instructions to run on (Windows)[./WINDOWS.md].

## Install

`npm install`
`npm run setup`

### Check SES integrity

The SES lockdown file should match the commited sha256 sum

`sha256sum -c SHA256SUMS`

### Podfile install for iOS

Expand Down
55 changes: 55 additions & 0 deletions SES_AND_LAVAMOAT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# LavaMoat and SES (Secure Ecmascript) maintenance

### Hermes

SES does not yet work with Hermes, so we had to disable it on both platforms https://github.com/facebook/hermes/issues/957

### SES injection

LavaMoat does not yet fully support react-native, there is a compatibility tracker [here](https://github.com/LavaMoat/docs/issues/12). Until then, we're using [SES](https://github.com/endojs/endo/tree/master/packages/ses) directly, injecting it directly into the InitializeCore which is the entrypoint for the react-native's bundle so it hardens our app as soon as possible in the process.

This is done through a patch on the react-native package, using `patch-package`.

We are currently using version `1.5.0` of SES, which is the latest version that works with react-native, it is loaded from the project root, `lockdown.umd.js`.


### Understanding SES Hardening

SES hardens JavaScript's built-in objects ("intrinsics") to prevent malicious code from modifying them. This includes:

- Object prototype methods (e.g. `Object.prototype.toString`)
- Array methods (e.g. `Array.prototype.push`)
- String methods
- Promise implementation
- Math object
- JSON object
- And other global objects

Common issues you might encounter:
1. "TypeError: Cannot assign to read only property": This means code is trying to modify a hardened object
2. "TypeError: Object.prototype.foo is not configurable": Attempting to add methods to hardened prototypes
3. "Cannot create property 'bar' on frozen object": Trying to modify frozen global objects

Debug tips:
- If you see these errors, check if your code or a third-party library is trying to:
- Modify built-in prototypes
- Add properties to global objects
- Override native methods
- Consider using proper alternatives:
- Create new objects instead of modifying built-ins
- Use class inheritance instead of prototype modification
- Keep modifications within your own object instances

### Updating SES

Once React Native is fully supported by LavaMoat, we'll replace the current patch with its official npm package. Until then, to update SES:

1. Update the `lockdown.umd.js` file to the latest supported SES lockdown file
2. Update the sha256sum of the lockdown library in the SHA256SUMS file

### Future Plans

We plan to migrate to LavaMoat's full implementation once React Native support is complete. This will provide:
- Better integration with the ecosystem
- Easier updates through npm
- Additional security features from LavaMoat
1 change: 1 addition & 0 deletions SHA256SUMS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
f10f4088c8bd9689f6108fac0e2c1d7ea3f0c1f159c64822e7830aa7018671a7 lockdown.umd.js
2 changes: 1 addition & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ newArchEnabled=false

# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
hermesEnabled=false

# Increase maximum size of memory allocation
org.gradle.jvmargs=-Xmx4096M
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { setJSExceptionHandler } from 'react-native-exception-handler';
import App from './src/App';
import { name as appName } from './app.json';
import { errorHandler } from './src/errorHandler';

import {
setBackgroundMessageListener,
setNotifeeBackgroundListener,
Expand Down
48 changes: 8 additions & 40 deletions ios/HathorMobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@
00E356EB1AD99517003FC87E /* Frameworks */,
00E356EC1AD99517003FC87E /* Resources */,
D6CF71901D46C404F80C1CBF /* [CP] Copy Pods Resources */,
3E7666BE09278503C27A1C65 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
Expand All @@ -192,7 +191,6 @@
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
E7A3890494F2D10544808206 /* [CP] Copy Pods Resources */,
98C5A10E99F2B977B3288BDB /* [CP-User] [RNFB] Core Configuration */,
05236F6C0A91F8F7AC940133 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
Expand Down Expand Up @@ -275,23 +273,6 @@
shellPath = /bin/sh;
shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
};
05236F6C0A91F8F7AC940133 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-HathorMobile/Pods-HathorMobile-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-HathorMobile/Pods-HathorMobile-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HathorMobile/Pods-HathorMobile-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
092A93BEE8FA44D1787A8BF9 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -314,23 +295,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3E7666BE09278503C27A1C65 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-HathorMobile-HathorMobileTests/Pods-HathorMobile-HathorMobileTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-HathorMobile-HathorMobileTests/Pods-HathorMobile-HathorMobileTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HathorMobile-HathorMobileTests/Pods-HathorMobile-HathorMobileTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
98C5A10E99F2B977B3288BDB /* [CP-User] [RNFB] Core Configuration */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -596,7 +560,7 @@
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
Expand Down Expand Up @@ -638,7 +602,9 @@
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl",
"-ld_classic",
"-Wl -ld_classic ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
Expand Down Expand Up @@ -678,7 +644,7 @@
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
Expand Down Expand Up @@ -716,7 +682,9 @@
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl",
"-ld_classic",
"-Wl -ld_classic ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
Expand Down
3 changes: 2 additions & 1 deletion ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ target 'HathorMobile' do
:path => config[:reactNativePath],

# Hermes is now enabled by default. Disable by setting this flag to false.
:hermes_enabled => flags[:hermes_enabled],
# We can't use Hermes with SES (https://github.com/facebook/hermes/issues/957)
:hermes_enabled => false,
:fabric_enabled => flags[:fabric_enabled],
# Enables Flipper.
#
Expand Down
Loading

0 comments on commit 2a65bf2

Please sign in to comment.