Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@endo/compartment-mapper

Package Overview
Dependencies
Maintainers
5
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@endo/compartment-mapper - npm Package Compare versions

Comparing version 0.9.2 to 1.0.0

28

package.json
{
"name": "@endo/compartment-mapper",
"version": "0.9.2",
"version": "1.0.0",
"description": "The compartment mapper assembles Node applications in a sandbox",

@@ -25,3 +25,6 @@ "keywords": [

"exports": {
".": "./index.js",
".": {
"types": "./types.d.ts",
"default": "./index.js"
},
"./import.js": "./import.js",

@@ -36,4 +39,4 @@ "./archive.js": "./archive.js",

"build": "exit 0",
"prepack": "tsc --build jsconfig.build.json",
"postpack": "git clean -f '*.d.ts*'",
"build:types": "tsc --build tsconfig.build.json",
"clean:types": "git clean -f '*.d.ts*'",
"cover": "c8 ava",

@@ -43,3 +46,3 @@ "lint": "yarn lint:types && yarn lint:js",

"lint:js": "eslint .",
"lint:types": "tsc -p jsconfig.json",
"lint:types": "tsc",
"prettier-fixtures": "prettier --write --with-node-modules './test/fixtures-*/**/*.*js'",

@@ -49,6 +52,6 @@ "test": "ava"

"dependencies": {
"@endo/cjs-module-analyzer": "^0.2.35",
"@endo/static-module-record": "^0.8.2",
"@endo/zip": "^0.2.35",
"ses": "^0.18.8"
"@endo/cjs-module-analyzer": "^1.0.0",
"@endo/static-module-record": "^1.0.0",
"@endo/zip": "^1.0.0",
"ses": "^1.0.0"
},

@@ -63,3 +66,3 @@ "devDependencies": {

"eslint-plugin-eslint-comments": "^3.1.2",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-import": "^2.29.0",
"prettier": "^3.0.0",

@@ -101,3 +104,6 @@ "typescript": "~5.2.2"

},
"gitHead": "9c779d317c4b02133172dbe142c5b2d1727efc49"
"typeCoverage": {
"atLeast": 85.78
},
"gitHead": "6aa22009bf8128575c446aebceb0f9a01459d165"
}

@@ -0,1 +1,2 @@

// @ts-nocheck
/** quotes strings */

@@ -8,3 +9,5 @@ const q = JSON.stringify;

exportName => `\
${exportName}: cell(${q(exportName)}),
${q(exportName)}: cell(${q(exportName)}${
exportName !== 'default' ? '' : `, {}`
}),
`,

@@ -18,4 +21,5 @@ ),

return ({ imports = {} }) => {
const moduleCells = cells[num];
const cModule = Object.freeze(
Object.defineProperty({}, 'exports', cells[num].default),
Object.defineProperty({}, 'exports', moduleCells.default),
);

@@ -25,5 +29,17 @@ // TODO: specifier not found handling

functors[num](Object.freeze(requireImpl), cModule.exports, cModule);
Object.keys(cells[num])
// Update all named cells from module.exports.
Object.keys(moduleCells)
.filter(k => k !== 'default' && k !== '*')
.map(k => cells[num][k].set(cModule.exports[k]));
.map(k => moduleCells[k].set(cModule.exports[k]));
// Add new named cells from module.exports.
Object.keys(cModule.exports)
.filter(k => k !== 'default' && k !== '*')
.filter(k => moduleCells[k] === undefined)
.map(k => (moduleCells[k] = cell(k, cModule.exports[k])));
// Update the star cell from all cells.
const starExports = Object.create(null);
Object.keys(moduleCells)
.filter(k => k !== '*')
.map(k => Object.defineProperty(starExports, k, moduleCells[k]));
moduleCells['*'].set(Object.freeze(starExports));
};

@@ -30,0 +46,0 @@ /* eslint-enable no-undef */

@@ -98,2 +98,5 @@ // @ts-check

exit: true,
errorHint: `Blocked in loading. ${q(
moduleSpecifier,
)} was not in the archive and an attempt was made to load it as a builtin`,
});

@@ -100,0 +103,0 @@ const record = await exitModuleImportHook(moduleSpecifier);

@@ -223,2 +223,5 @@ // @ts-check

exit: true,
errorHint: `Blocked in loading. ${q(
moduleSpecifier,
)} was not in the compartment map and an attempt was made to load it as a builtin`,
});

@@ -255,6 +258,4 @@ if (archiveOnly) {

const candidates = [moduleSpecifier];
if (moduleSpecifier !== '.') {
for (const candidateSuffix of searchSuffixes) {
candidates.push(`${moduleSpecifier}${candidateSuffix}`);
}
for (const candidateSuffix of searchSuffixes) {
candidates.push(`${moduleSpecifier}${candidateSuffix}`);
}

@@ -261,0 +262,0 @@

@@ -21,3 +21,3 @@ export function mapParsers(languageForExtension: Record<string, Language>, languageForModuleSpecifier: Record<string, string>, parserForLanguage: Record<string, ParserImplementation>, moduleTransforms?: ModuleTransforms): ParseFn;

export type LinkOptions = import('./types.js').LinkOptions;
export type ERef<T_1> = import('@endo/eventual-send').ERef<T>;
export type ERef<T_1> = any;
//# sourceMappingURL=link.d.ts.map

@@ -22,3 +22,2 @@ // @ts-check

ATTENUATORS_COMPARTMENT,
diagnoseMissingCompartmentError,
attenuateGlobals,

@@ -236,6 +235,10 @@ makeDeferredAttenuatorsProvider,

if (foreignModuleSpecifier !== undefined) {
// archive goes through foreignModuleSpecifier for local modules too
if (!moduleSpecifier.startsWith('./')) {
// archive goes through foreignModuleSpecifier for local modules too
// This code path seems to only be reached on subsequent imports of the same specifier in the same compartment.
// The check should be redundant and is only left here out of abundance of caution.
enforceModulePolicy(moduleSpecifier, compartmentDescriptor, {
exit: false,
errorHint:
'This check should not be reachable. If you see this error, please file an issue.',
});

@@ -249,8 +252,3 @@ }

foreignCompartmentName,
)}${diagnoseMissingCompartmentError({
moduleSpecifier,
compartmentDescriptor,
foreignModuleSpecifier,
foreignCompartmentName,
})}`,
)}}`,
);

@@ -285,16 +283,13 @@ }

foreignCompartmentName,
)}${diagnoseMissingCompartmentError({
moduleSpecifier,
compartmentDescriptor,
foreignModuleSpecifier,
foreignCompartmentName,
})}`,
)}`,
);
}
// Despite all non-exit modules not allowed by policy being dropped
// while building the graph, this check is necessary because module
// is written back to the compartment map below.
enforceModulePolicy(scopePrefix, compartmentDescriptor, {
exit: false,
errorHint: `Blocked in linking. ${q(
moduleSpecifier,
)} is part of the compartment map and resolves to ${q(
foreignCompartmentName,
)}.`,
});

@@ -301,0 +296,0 @@ // The following line is weird.

@@ -569,3 +569,3 @@ // @ts-check

* for selecting relevant exports, e.g., "browser" or "node".
* @param {object} policy
* @param {object|undefined} policy
* @returns {CompartmentMapDescriptor}

@@ -615,7 +615,2 @@ */

);
// do not include compartments for packages not covered by policy
if (policy && !packagePolicy) {
// eslint-disable-next-line no-continue
continue;
}

@@ -622,0 +617,0 @@ /**

@@ -135,2 +135,7 @@ // @ts-check

const require = (/** @type {string} */ importSpecifier) => {
if (!has(resolvedImports, importSpecifier)) {
throw new Error(
`Cannot find module "${importSpecifier}" in "${location}"`,
);
}
const namespace = compartment.importNow(resolvedImports[importSpecifier]);

@@ -137,0 +142,0 @@ // If you read this file carefully, you'll see it's not possible for a cjs module to not have the default anymore.

@@ -46,3 +46,3 @@ // @ts-check

*
* @param {*} policyValue
* @param {any} policyValue
* @returns {boolean}

@@ -126,3 +126,3 @@ */

allegedPackagePolicy === packagePolicy && !isArray(allegedPackagePolicy),
`${path} must be an object, got ${allegedPackagePolicy}${inUrl}`,
`${path} must be an object, got ${q(allegedPackagePolicy)}${inUrl}`,
);

@@ -129,0 +129,0 @@ const {

@@ -10,10 +10,4 @@ /**

export function attenuateGlobals(globalThis: object, globals: object, packagePolicy: object, attenuators: DeferredAttenuatorsProvider, pendingJobs: Array<Promise<any>>, name?: string): void;
export function enforceModulePolicy(specifier: string, compartmentDescriptor: object, info?: object): void;
export function enforceModulePolicy(specifier: string, compartmentDescriptor: import('./types.js').CompartmentDescriptor, info?: object): void;
export function attenuateModuleHook(specifier: string, originalModuleRecord: ThirdPartyStaticModuleInterface, policy: object, attenuators: DeferredAttenuatorsProvider): Promise<ThirdPartyStaticModuleInterface>;
export function diagnoseMissingCompartmentError({ moduleSpecifier, compartmentDescriptor, foreignModuleSpecifier, foreignCompartmentName, }: {
moduleSpecifier: string;
compartmentDescriptor: object;
foreignModuleSpecifier: string;
foreignCompartmentName: string;
}): string;
export type PackageNamingKit = import('./types.js').PackageNamingKit;

@@ -20,0 +14,0 @@ export type AttenuationDefinition = import('./types.js').AttenuationDefinition;

@@ -20,3 +20,3 @@ // @ts-check

const { entries, values, assign, keys, freeze } = Object;
const { create, entries, values, assign, keys, freeze } = Object;
const q = JSON.stringify;

@@ -105,3 +105,3 @@

* @param {PackageNamingKit} namingKit
* @param {*} packagePolicy
* @param {any} packagePolicy
* @returns {boolean}

@@ -118,25 +118,2 @@ */

const validateDependencies = (policy, canonicalName) => {
const packages = policy.resources[canonicalName].packages;
if (!packages || isAllowingEverything(packages)) {
return;
}
const packageNames = keys(packages);
const attenuators = detectAttenuators(policy);
// Join attenuators with packageNames into a Set to deduplicate and check if all are listed in policy.resources
const allSpecifiers = new Set([...packageNames, ...attenuators]);
for (const specifier of allSpecifiers) {
if (!(specifier in policy.resources)) {
throw Error(
`Package ${q(specifier)} is allowed for ${q(
canonicalName,
)} to import but its policy is not defined. Please add a policy for ${q(
specifier,
)}`,
);
}
}
};
/**

@@ -160,16 +137,10 @@ * Returns the policy applicable to the canonicalName of the package

defaultAttenuator: policy.defaultAttenuator,
packages: detectAttenuators(policy).reduce((packages, specifier) => {
packages[specifier] = true;
return packages;
}, {}),
packages: 'any',
};
}
if (policy.resources && policy.resources[canonicalName]) {
validateDependencies(policy, canonicalName);
if (policy.resources && policy.resources[canonicalName] !== undefined) {
return policy.resources[canonicalName];
} else {
console.warn(
`No policy for '${canonicalName}', omitting from compartment map.`,
);
return undefined;
// Allow skipping policy entries for packages with no powers.
return create(null);
}

@@ -364,2 +335,8 @@ };

const diagnoseModulePolicy = errorHint => {
if (!errorHint) {
return '';
}
return ` (info: ${errorHint})`;
};
/**

@@ -369,7 +346,11 @@ * Throws if importing of the specifier is not allowed by the policy

* @param {string} specifier
* @param {object} compartmentDescriptor
* @param {import('./types.js').CompartmentDescriptor} compartmentDescriptor
* @param {object} [info]
*/
export const enforceModulePolicy = (specifier, compartmentDescriptor, info) => {
const { policy, modules } = compartmentDescriptor;
export const enforceModulePolicy = (
specifier,
compartmentDescriptor,
info = {},
) => {
const { policy, modules, label } = compartmentDescriptor;
if (!policy) {

@@ -382,5 +363,7 @@ return;

throw Error(
`Importing ${q(specifier)} was not allowed by policy packages:${q(
`Importing ${q(specifier)} in ${q(
label,
)} was not allowed by packages policy ${q(
policy.packages,
)}`,
)}${diagnoseModulePolicy(info.errorHint)}`,
);

@@ -395,3 +378,3 @@ }

policy.builtins,
)}`,
)}${diagnoseModulePolicy(info.errorHint)}`,
);

@@ -470,59 +453,1 @@ }

};
const padDiagnosis = text => ` (${text})`;
/**
* Provide dignostic information for a missing compartment error
*
* @param {object} args
* @param {string} args.moduleSpecifier
* @param {object} args.compartmentDescriptor
* @param {string} args.foreignModuleSpecifier
* @param {string} args.foreignCompartmentName
* @returns {string}
*/
export const diagnoseMissingCompartmentError = ({
moduleSpecifier,
compartmentDescriptor,
foreignModuleSpecifier,
foreignCompartmentName,
}) => {
const { policy, name, scopes } = compartmentDescriptor;
if (policy) {
if (!policy.packages) {
return padDiagnosis(
`There were no allowed packages specified in policy for ${q(name)}`,
);
}
if (name === ATTENUATORS_COMPARTMENT) {
return padDiagnosis(
`Attenuator ${q(
moduleSpecifier,
)} was imported but there is no policy resources entry defined for it.`,
);
}
const scopeNames = entries(scopes)
.filter(([_name, scope]) => scope.compartment === foreignCompartmentName)
.map(([scopeName]) => scopeName);
if (scopeNames.length === 1 && scopeNames[0] === moduleSpecifier) {
return padDiagnosis(
`Package ${q(
moduleSpecifier,
)} is missing. Are you sure there is an entry in policy resources specified for it?`,
);
} else {
return padDiagnosis(
`Package ${q(moduleSpecifier)} resolves to ${q(
foreignModuleSpecifier,
)} in ${q(
foreignCompartmentName,
)} which seems disallowed by policy. There is likely an override defined that causes another package to be imported as ${q(
moduleSpecifier,
)}.`,
);
}
}
// Omit diagnostics when parent package had no policy - it means there was no policy.
return '';
};

@@ -110,3 +110,3 @@ export type FinalStaticModuleType = import('ses').FinalStaticModuleType;

export type CanonicalFn = (location: string) => Promise<string>;
export type HashFn = (bytes: Uint8Array) => string;
export type HashFn = (bytes: string | Uint8Array) => string;
export type Application = {

@@ -113,0 +113,0 @@ import: ExecuteFn;

@@ -136,3 +136,3 @@ // @ts-check

* @callback HashFn
* @param {Uint8Array} bytes
* @param {string | Uint8Array} bytes
* @returns {string} hash

@@ -139,0 +139,0 @@ */

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc