Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: SES lockdown v1.1.0 on Android (Hermes) #8009

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 44 additions & 16 deletions ses.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
// [email protected]
// hacked for Hermes edition (Android)
// - Bundling w/o async/await (Gradle task: createBundleProdDebugJsAndAssets)
// - by Metro via RN CLI (run-android --variant=prodDebug)
// - Building w/o async/await (Gradle task: installProdDebug)
// - Running w current modded SES iteration w/o hardenIntrinsics()
// - TODO: final updates, release-mode, codemod, lockdown opt
'use strict';
(() => {
const functors = [
Expand Down Expand Up @@ -3731,6 +3737,7 @@ function initProperty(obj, name, desc) {
preDesc.enumerable!== desc.enumerable||
preDesc.configurable!== desc.configurable)
{
// Thrown on Hermes: "Conflicting definitions of %InertAsyncFunction%"
throw TypeError( `Conflicting definitions of ${name}`);
}
}
Expand Down Expand Up @@ -3788,6 +3795,7 @@ const makeIntrinsicsCollector= ()=> {
}
const namePrototype= permit.prototype;
if( !namePrototype) {
// Thrown on Hermes: "lockdown.prototype property not whitelisted"
throw TypeError( `${name}.prototype property not whitelisted`);
}
if(
Expand Down Expand Up @@ -4022,6 +4030,7 @@ function whitelistIntrinsics(
}

// We can't clean [[prototype]], therefore abort.
// Hermes: "Unexpected intrinsic intrinsics.isFinite.__proto__ at %FunctionPrototype%"
throw TypeError( `Unexpected intrinsic ${path}.__proto__ at ${protoName}`);
}

Expand Down Expand Up @@ -4544,7 +4553,7 @@ function tameRegExpConstructor(regExpTaming= 'safe') {

const speciesDesc= getOwnPropertyDescriptor(FERAL_REG_EXP, speciesSymbol);
if( !speciesDesc) {
throw TypeError('no RegExp[Symbol.species] descriptor');
throw TypeError('no RegExp[Symbol.species] descriptor'); // Thrown on Hermes
}

defineProperties(ResultRegExp, {
Expand Down Expand Up @@ -7883,7 +7892,9 @@ const loadRecord= (
return moduleRecord;
};

const loadWithoutErrorAnnotation= async(
// Metro bundle error via RN CLI on Hermes: "async functions are unsupported"
// on Gradle task: createBundleProdDebugJsAndAssets
const loadWithoutErrorAnnotation= (
compartmentPrivateFields,
moduleAliases,
compartment,
Expand Down Expand Up @@ -7923,7 +7934,7 @@ const loadWithoutErrorAnnotation= async(
}
// Behold: recursion.
// eslint-disable-next-line no-use-before-define
const aliasRecord= await memoizedLoadWithErrorAnnotation(
const aliasRecord= memoizedLoadWithErrorAnnotation( // "await" keyword removed for Hermes
compartmentPrivateFields,
moduleAliases,
alias.compartment,
Expand All @@ -7940,7 +7951,7 @@ const loadWithoutErrorAnnotation= async(
return mapGet(moduleRecords, moduleSpecifier);
}

const staticModuleRecord= await importHook(moduleSpecifier);
const staticModuleRecord= importHook(moduleSpecifier); // "await" keyword removed for Hermes

if( staticModuleRecord=== null|| typeof staticModuleRecord!== 'object') {
Fail `importHook must return a promise for an object, for module ${q(
Expand Down Expand Up @@ -7990,7 +8001,7 @@ const loadWithoutErrorAnnotation= async(
}
// Behold: recursion.
// eslint-disable-next-line no-use-before-define
const aliasRecord= await memoizedLoadWithErrorAnnotation(
const aliasRecord= memoizedLoadWithErrorAnnotation( // "await" keyword removed for Hermes
compartmentPrivateFields,
moduleAliases,
staticModuleRecord.compartment,
Expand Down Expand Up @@ -8018,7 +8029,10 @@ const loadWithoutErrorAnnotation= async(

};

const memoizedLoadWithErrorAnnotation= async(
// Metro bundle error via RN CLI on Hermes: "async functions are unsupported"
// on Gradle task: createBundleProdDebugJsAndAssets
// Does this need to be "async" anyway?
const memoizedLoadWithErrorAnnotation= (
compartmentPrivateFields,
moduleAliases,
compartment,
Expand Down Expand Up @@ -8077,7 +8091,9 @@ const memoizedLoadWithErrorAnnotation= async(
* compartment and the specifier of the module within its own compartment.
* This graph is then ready to be synchronously linked and executed.
*/
const load= async(
// Metro bundle error via RN CLI on Hermes: "async functions are unsupported"
// on Gradle task: createBundleProdDebugJsAndAssets
const load= (
compartmentPrivateFields,
moduleAliases,
compartment,
Expand Down Expand Up @@ -8117,7 +8133,7 @@ const load= async(
// `errors` accumulator.
for( const job of pendingJobs) {
// eslint-disable-next-line no-await-in-loop
await job;
job; // "await" keyword removed for Hermes
}

// Throw an aggregate error if there were any errors.
Expand Down Expand Up @@ -9499,8 +9515,10 @@ const getAnonymousIntrinsics= ()=> {

// 25.3.1 The AsyncGeneratorFunction Constructor

// Metro bundle error via RN CLI on Hermes: "async generators are unsupported"
// on Gradle task: createBundleProdDebugJsAndAssets
// eslint-disable-next-line no-empty-function
async function* AsyncGeneratorFunctionInstance() { }
function* AsyncGeneratorFunctionInstance() { }
const AsyncGeneratorFunction= getConstructorOf(
AsyncGeneratorFunctionInstance);

Expand All @@ -9514,7 +9532,7 @@ const getAnonymousIntrinsics= ()=> {
// 25.7.1 The AsyncFunction Constructor

// eslint-disable-next-line no-empty-function
async function AsyncFunctionInstance() { }
async function AsyncFunctionInstance() { } // "async" keyword here seems fine on Hermes
const AsyncFunction= getConstructorOf(AsyncFunctionInstance);

const intrinsics= {
Expand Down Expand Up @@ -9657,6 +9675,7 @@ const tameSymbolConstructor= ()=> {
{ ...desc, configurable: true}]));


// @react-native/polyfills FatalError on Hermes: "property is not configurable
defineProperties(SharedSymbol, descs);

return { '%SharedSymbol%': SharedSymbol};
Expand Down Expand Up @@ -10001,6 +10020,7 @@ const assertDirectEvalAvailable= ()=> {
}
if( !allowed) {
// See https://github.com/endojs/endo/blob/master/packages/ses/error-codes/SES_DIRECT_EVAL.md
// Thrown on Hermes
throw TypeError(
`SES cannot initialize unless 'eval' is the original intrinsic 'eval', suitable for direct-eval (dynamically scoped eval) (SES_DIRECT_EVAL)`);

Expand Down Expand Up @@ -10088,7 +10108,8 @@ const repairIntrinsics= (options= {})=> {
// trace retained:
priorRepairIntrinsics.stack;

assertDirectEvalAvailable();
// SES TypeError thrown on Hermes: SES_DIRECT_EVAL (ses.cjs#9622)
// assertDirectEvalAvailable();

/**
* Because of packagers and bundlers, etc, multiple invocations of lockdown
Expand Down Expand Up @@ -10151,12 +10172,18 @@ const repairIntrinsics= (options= {})=> {
addIntrinsics(tameDateConstructor(dateTaming));
addIntrinsics(tameErrorConstructor(errorTaming, stackFiltering));
addIntrinsics(tameMathObject(mathTaming));
addIntrinsics(tameRegExpConstructor(regExpTaming));
addIntrinsics(tameSymbolConstructor());

addIntrinsics(getAnonymousIntrinsics());
// SES TypeError thrown on Hermes: "no RegExp[Symbol.species] descriptor" (ses.cjs#4472)
// addIntrinsics(tameRegExpConstructor(regExpTaming));

completePrototypes();
// @react-native/polyfills FatalError on Hermes: "property is not configurable (ses.cjs#9481)
// addIntrinsics(tameSymbolConstructor());

// SES TypeError thrown on Hermes: "Conflicting definitions of %InertAsyncFunction%" (ses.cjs#3688)
addIntrinsics(getAnonymousIntrinsics()); // No longer problematic on Hermes in this current iteration of ses.cjs

// SES TypeError thrown on Hermes: "lockdown.prototype property not whitelisted" (ses.cjs#3730)
// completePrototypes();

const intrinsics= finalIntrinsics();

Expand Down Expand Up @@ -10224,7 +10251,8 @@ const repairIntrinsics= (options= {})=> {
// Remove non-standard properties.
// All remaining function encountered during whitelisting are
// branded as honorary native functions.
whitelistIntrinsics(intrinsics, markVirtualizedNativeFunction);
// SES TypeError thrown on Hermes: "Unexpected intrinsic intrinsics.isFinite.__proto__ at %FunctionPrototype%""
// whitelistIntrinsics(intrinsics, markVirtualizedNativeFunction);

// Initialize the powerful initial global, i.e., the global of the
// start compartment, from the intrinsics.
Expand Down
Loading