{"id":39024094,"url":"https://github.com/sateffen/node-module-confinement","last_synced_at":"2026-01-17T17:30:38.961Z","repository":{"id":57311456,"uuid":"146211396","full_name":"sateffen/node-module-confinement","owner":"sateffen","description":"Confining require and node_modules for the extra bit of security","archived":false,"fork":false,"pushed_at":"2023-10-20T20:50:12.000Z","size":749,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-28T06:42:37.589Z","etag":null,"topics":["confine","confinement","isolation","module","nodejs","policy","require","security"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sateffen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-26T19:48:18.000Z","updated_at":"2023-01-14T13:36:46.000Z","dependencies_parsed_at":"2023-02-09T19:45:32.431Z","dependency_job_id":null,"html_url":"https://github.com/sateffen/node-module-confinement","commit_stats":{"total_commits":86,"total_committers":2,"mean_commits":43.0,"dds":"0.011627906976744207","last_synced_commit":"9f3fa8d69bfbbe73d334545fe48a6a3b1fe1ffb8"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/sateffen/node-module-confinement","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sateffen%2Fnode-module-confinement","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sateffen%2Fnode-module-confinement/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sateffen%2Fnode-module-confinement/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sateffen%2Fnode-module-confinement/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sateffen","download_url":"https://codeload.github.com/sateffen/node-module-confinement/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sateffen%2Fnode-module-confinement/sbom","scorecard":{"id":801376,"data":{"date":"2025-08-11","repo":{"name":"github.com/sateffen/node-module-confinement","commit":"59b13a87cc814457ea551b316bfbeede19f2d04a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/qualityassurance.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/qualityassurance.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/sateffen/node-module-confinement/qualityassurance.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/qualityassurance.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/sateffen/node-module-confinement/qualityassurance.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T10:35:09.946Z","repository_id":57311456,"created_at":"2025-08-23T10:35:09.946Z","updated_at":"2025-08-23T10:35:09.946Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28512911,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["confine","confinement","isolation","module","nodejs","policy","require","security"],"created_at":"2026-01-17T17:30:38.859Z","updated_at":"2026-01-17T17:30:38.947Z","avatar_url":"https://github.com/sateffen.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# node-module-confinement\n\nThis package provides a simple way for confining modules and preventing them to load unwanted other modules,\nor redirect modules to load to different ones.\n\nYou can set up a blacklist and a whitelist for this confinement. You can tell the confinement to prevent node\ninternal modules completely, only allowing a few ones by whitelist. Additionally, you can redirect require calls\nto your own modules, like redirecting `fs` to `safe-fs`, which provides a trusted subset of fs-access.\n\nIf anything defies the confinement, an error is thrown to prevent anything bad from happening. The error tells\nyou which confinement was defied and which module did this.\n\nOn top of all that, this module comes with some \"addons\", which allow you to setup some traps to prevent unwanted\ncode execution methods.\n\n## Why\n\nUsing dependencies is dangerous. Installing simple npm-packages might download tons of other unknown dependencies,\nwhich you can't review all. If only one of such dependencies contain malicious code, you're screwed.\n\nThis module helps to reduce the attack-surface, as you can limit access to node internal modules or critical configuration\nfiles. That way bad code leads to an error, preventing bad stuff from happening.\n\nSo this module helps with preventing supply-chain-attacks or dependency-attacks, and helps to secure your application\nby simply enforcing policies.\n\n## API\n\nThe main API exists of only a single function: `setup`. The signature is: `setup(moduleContext, confinementConfiguration)`\n\nThe `moduleContext` is the current `module` value. This is used to resolve all modules referenced by the\n`confinementConfiguration`.\n\nThe `confinementConfiguration` is the most important part, and looks something like this:\n\n```js\nconst confinementConfiguration = {\n    defaultConfinement: {\n        allowBuiltIns: true\n        blackList: [],\n        whiteList: [],\n        redirect: {}\n    },\n    confinements: {\n        './some/module.js': {\n            applyToChildren: false,\n            allowBuiltIns: false\n            blackList: [],\n            whiteList: ['fs', 'path'],\n            redirect: {}\n        },\n        './some/other/module.js': {\n            applyToChildren: false,\n            allowBuiltIns: false\n            blackList: [],\n            whiteList: [],\n            redirect: {}\n        }\n    },\n    addons: {\n        trapEval: false,\n        trapFunction: false\n    }\n};\n```\n\n### Confinements\n\nSo, bascially a confinement consists of 4 main rules: `allowBuiltIns`, `whiteList`, `blackList` and `redirect`. The rules are applied as follows:\n\nFirst of let's look at `whiteList` and `blackList`, as they are the most straight forward. `whiteList`ed modules are allowed by\ndefault, `blackList`ed modules are denied by default. All modules passed in this arrays get resolved to their actual module-filename.\nTo do so all modules get resolved relative to given `moduleContext` (which was passed as first parameter to `setup`-function).\n\nThe second part to consider is the `allowBuiltIns` flag, which tells to allow or deny all builtin nodejs modules. So if you put `allowBuiltIns=false`\ncalling stuff like `require('fs')` will throw an error. This is basically a shortcut to add all node builtin modules to the `blackList`. To allow\nloading at least some builtin modules, you can pass them to the `whiteList`, so you can write a confinement like `{allowBuiltIns: false, whiteList: ['fs']}`\nto allow `require('fs')`, but deny all other builtins like `require('path')`.\n\nAfter applying all the rules above, we know whether the current `require` call is allowed or forbidden. If it's allowed, the last property comes into\nplay: `redirect`. This contains a map of `module -\u003e module` contents. So if the module wants to load a certain other module, you can redirect the call to\nload yet another module. This is useful for example when redirecting builtins to mocks or limited variants, something like:\n\n```js\nconst confinementConfiguration {\n    defaultConfinement: {\n        allowBuiltIns: false,\n        whiteList: ['fs'],\n        redirect: {\n            'fs': './myfsmock.js'\n        }\n    }\n}\n```\n\nThat way we can redirect require calls to different modules for security purpose (or whatever).\n\nThe last option of a confinement is `applyToChildren`, which is a flag only applied during confinement evaluation. To know understand\nthis flag, you have to understand how confinements get resolved:\n\n* First the module, that should be loaded, gets resolved to its module-filename\n* Then we check, whether the resolved module-filename matches with any `confinements`-entry. If so, we use this confinement\n* Because we have no specific confinement, we traverse the module-tree upwards, to check whether any parent has a confinement.\nIf any parent has a confinement, we check the `applyToChildren` flag. If it's true, we use this confinement. If it's false,\nwe traverse the tree upwards up to the root module (provided `moduleContext`)\n* If we couldn't find any confinement up till now, we use the `defaultConfinement`\n* If the `defaultConfinement` was empty, no confinement is applied\n\nThis should make it obvious, what `applyToChildren` does.\n\nThis should explain everything about confinements, that you need to know.\n\n### Addons\n\nAnother special topic is \"addons\". This module contains some addons, that help with securing your application. You can apply the\nfollowing addons by simply setting them to `true` in the configuration.\n\n#### trapEval\n\nThis is pretty obvious: Proxy the global `eval` function and throw an error each time it gets called. This way `eval` doesn't work\nanymore, and malicious `eval`-calls are prevented.\n\n#### trapFunction\n\nThis is basically as obvious as the previous one, but most people don't know about this one: The function constructor is basically\na hidden `eval` function. Stuff like `Function('console.log(process.pid);')()` might not do bad, but does the same as\n`eval('console.log(process.pid);')`, so its basically eval in disguise.\n\nTo prevent usage of this hidden eval-like stuff, you can apply a trap by enabling this option. This trap will prevent all `Function(...)`\nand `new Function(...)` calls and throw an error each time it happens.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsateffen%2Fnode-module-confinement","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsateffen%2Fnode-module-confinement","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsateffen%2Fnode-module-confinement/lists"}