var CoreModule = require('module'); var Shield = function(spec) { var exceptions = []; var cache = new Map(); var whitelist = spec.mode === 'white-list'; var originals = {}; originals.require = CoreModule.prototype.require; originals.load = CoreModule.prototype.constructor._load; var isAllowed = function(path, module) { var cached = cache.has(path); if(cached) return cache.get(path); var caught = exceptions.some(function(x) { var toRequirePattern = new RegExp(x.toRequire); var caughtToRequire = toRequirePattern.test(path); if(!x.fromModules || !caughtToRequire) { return caughtToRequire; } var fromModulesPattern = new RegExp(x.fromModules); var caughtFromModules = fromModulesPattern.test(module.filename); return caughtFromModules; }); var allowed = caught?whitelist:!whitelist; cache.set(path, allowed); return allowed; }; var localLoad = function(path, parent, isMain) { var allowed = isAllowed(path); if(allowed) { return originals.load(path, parent, isMain); } else { // TODO: The module object is wrong here throw new Error(`Mode: ${spec.mode}. '${module.filename}' attempted to load('${path}')`); } }; var localRequire = function(path) { var module = this; var allowed = isAllowed(path, module); if(allowed) { var required = originals.require(path); return required; } else { throw new Error(`Mode: ${spec.mode}. '${module.filename}' attempted to require('${path}')`); } }; CoreModule.prototype.require = localRequire; CoreModule.prototype.constructor._load = localLoad; var except = function(toRequire, fromModules) { exceptions.push({ toRequire: toRequire, fromModules: fromModules }); }; return { require: localRequire, except: except }; }; module.exports = function(spec) { var result = new Shield(spec); return result; };