Research
Security News
Kill Switch Hidden in npm Packages Typosquatting Chalk and Chokidar
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
stealthy-require
Advanced tools
The closest you can get to require something with bypassing the require cache
The stealthy-require npm package allows you to require a module in a way that avoids caching, enabling you to load the module fresh every time. This can be useful for testing, mocking, or when you need to ensure that the module's state is reset.
Require a module without caching
This feature allows you to require a module without it being cached. This is useful when you need to ensure that the module is loaded fresh every time, such as in testing scenarios.
const stealthyRequire = require('stealthy-require');
// Load the module without caching
const myModule = stealthyRequire(require.cache, function () {
return require('my-module');
});
Require a module with specific dependencies
This feature allows you to require a module along with specific dependencies. This can be useful when you need to control the environment in which the module is loaded.
const stealthyRequire = require('stealthy-require');
// Load the module with specific dependencies
const myModule = stealthyRequire(require.cache, function () {
return require('my-module');
}, function () {
require('dependency1');
require('dependency2');
});
Proxyquire is a powerful tool for overriding dependencies during testing. Unlike stealthy-require, which focuses on avoiding cache, proxyquire allows you to mock dependencies, making it more suitable for complex testing scenarios.
Mock-require is another package that allows you to mock modules during testing. It provides a simpler API compared to proxyquire and is focused on replacing modules with mocks, similar to stealthy-require but with a different approach.
Clear-require is a package that allows you to clear a module from the require cache. While stealthy-require avoids caching altogether, clear-require gives you control over when to clear the cache, providing more flexibility.
This is probably the closest you can currently get to require something in node.js with completely bypassing the require cache.
stealthy-require
works like this:
The restrictions are:
This means you should have a close look at all internal require calls before you decide to use this library.
This is a module for node.js and is installed via npm:
npm install stealthy-require --save
Let's say you want to bypass the require cache for this require call:
var request = require('request');
With stealthy-require
you can do that like this:
var stealthyRequire = require('stealthy-require');
var requestFresh = stealthyRequire(require.cache, function () {
return require('request');
});
The require cache is bypassed for the module you require (i.e. request
) as well as all modules the module requires (i.e. http
and many more).
Sometimes the require cache shall not be bypassed for specific modules. E.g. request
is required but tough-cookie
– on which request
depends on – shall be required using the regular cache. For that you can pass two extra arguments to stealthyRequire(...)
:
module
variablevar stealthyRequire = require('stealthy-require');
var requestFresh = stealthyRequire(require.cache, function () {
return require('request');
},
function () {
require('tough-cookie'); // No return needed
// You can require multiple modules here
}, module);
require.cache
. However, as of browserify@13.0.1
the cache is passed as the 6th argument to CommonJS modules. Thus you can pass this argument instead:// Tweak for Browserify - using arguments[5] instead of require.cache
var requestFresh = stealthyRequire(arguments[5], function () {
return require('request');
});
If you are using stealthy-require
in node.js and repeatedly require fresh module instances the module.children
array will hold all module instances which prevents unneeded instances to be garbage collected.
Assume your code calls doSomething()
repeatedly.
var stealthyRequire = require('stealthy-require');
function doSomething() {
var freshInstance = stealthyRequire(require.cache, function () {
return require('some-module');
});
return freshInstance.calc();
}
After doSomething()
returns freshInstance
is not used anymore but won’t be garbage collected because module.children
still holds a reference. The solution is to truncate module.children
accordingly:
var stealthyRequire = require('stealthy-require');
function doSomething() {
var initialChildren = module.children.slice(); // Creates a shallow copy of the array
var freshInstance = stealthyRequire(require.cache, function () {
return require('some-module');
});
module.children = initialChildren;
return freshInstance.calc();
}
The slice
operation removes all new module.children
entries created during the stealthyRequire(...)
call and thus freshInstance
gets garbage collected after doSomething()
returns.
// 1. Load stealthy-require
var stealthyRequire = require('stealthy-require');
// This does nothing but loading the code.
// It has no side-effects like patching the module loader or anything.
// Any regular require works as always.
var request1 = require('request');
// 2. Call stealthyRequire with passing the require cache and a callback.
var requestFresh = stealthyRequire(require.cache, function () {
// 2a. Before this callback gets called the require cache is cleared.
// 2b. Any require taking place here takes place on a clean require cache.
// Since the require call is part of the user's code it also works with module bundlers.
return require('request');
// Anything returned here will be returned by stealthyRequire(...).
// 2c. After this callback gets called the require cache is
// - cleared again and
// - restored to its old state before step 2.
});
// Any regular require again works as always.
// In this case require returns the cached request module instance.
var request2 = require('request');
// And voilà:
request1 === request2 // -> true
request1 === requestFresh // -> false
To set up your development environment for stealthy-require
:
cd
to the main folder,npm install
,npm install gulp -g
if you haven't installed gulp globally yet, andgulp dev
. (Or run node ./node_modules/.bin/gulp dev
if you don't want to install gulp globally.)gulp dev
watches all source files and if you save some changes it will lint the code and execute all tests. The test coverage report can be viewed from ./coverage/lcov-report/index.html
.
If you want to debug a test you should use gulp test-without-coverage
to run all tests without obscuring the code by the test coverage instrumentation.
undefined
entries from appearing in require.cache
(Thanks to @jasperjn from reporting this in issue #4)In case you never heard about the ISC license it is functionally equivalent to the MIT license.
See the LICENSE file for details.
FAQs
The closest you can get to require something with bypassing the require cache
The npm package stealthy-require receives a total of 3,572,439 weekly downloads. As such, stealthy-require popularity was classified as popular.
We found that stealthy-require demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.