Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
An easy-to-use mock for child_process.spawn
.
spawn
was invoked and the details
of every invocation are available as attributes on the mock for later assertionsvar mockSpawn = require('mock-spawn');
// override child_process.spawn
// this is a simplistic example; you can use a library like `mockery` to
// set a new instance for every test. See examples/complete/test.js
var mySpawn = mockSpawn();
require('child_process').spawn = mySpawn;
// at this point you have mocked child_process.spawn to always exit 0
// and write nothing to stdout or stderr
// let's change the default processing to exit 1 always and write something
// to stdout
mySpawn.setDefault(mySpawn.simple(1 /* exit code */, 'hello world' /* stdout */));
// let's tell the mock to do specific things on sequential calls
// in this case we exit 0 on the first call, 1 on the second call and so on
mySpawn.sequence.add(mySpawn.simple(0));
mySpawn.sequence.add(mySpawn.simple(1));
mySpawn.sequence.add(function (cb) {
setTimeout(function () { return cb(2); }, 2000);
});
mySpawn.sequence.add(function (cb) {
// test the error handling of your library
this.emit('error', new Error('spawn ENOENT');
setTimeout(function() { return cb(8); }, 10);
});
mySpawn.sequence.add({throws:new Error('spawn ENOENT')});
// the fourth call to spawn will use the default function we set up to exit 1
// the fifth call to spawn will emit an error and emit exit with code 8 on the
// next tick of the event loop
// the sixth call to spawn will throw an error synchronously
// call your test library here that invokes spawn the way you expect it to
lib.doSomething(function (err) {
/* after the test is done running, you can make assertions like so */
assert.equal(6, mySpawn.calls.length);
var firstCall = mySpawn.calls[0];
assert.equal('ls', firstCall.command);
assert.deepEqual([ '-l' ], firstCall.args);
assert.equal(0, firstCall.exitCode);
});
var mockSpawn = require('mock-spawn');
// basic stuff
var mySpawn = mockSpawn();
require('child_process').spawn = mySpawn;
// we are now testing if our library under test retries spawn commands on error
// when executing the `foo` command
var count = 0;
mySpawn.setStrategy(function (command, args, opts) {
if (command !== 'foo') { return null; } // use default
if (++count < 3) {
return mySpawn.simple(1); //exit 1 immediately
}
return function (cb) {
this.stdout.write('output data my library expects');
return cb(0); // and exit 0
};
});
The runner function accepts a single callback that needs to be called with an
exit code and optionally a signal name. If you define a throws
property on
the runner object, it will throw that error synchronously to mimic the
behavior of child_process.spawn
. It will ignore everything else in this case,
and it will not "run" at all.
CAVEAT: The throws
value must be an instanceof Error
.
The runner function has access to the following attributes via this
this.stdout
- the standard output of the process to which it can writethis.stderr
- the standard error of the process to which it can writethis.command
- the command for the spawn
callthis.args
- the args for the spawn
callthis.opts
- the options object passed to the spawn
callthis.emit
- the emit method of the underlying EventEmitter
The process "runs" until the runner calls the callback.
The strategy function accepts 3 arguments: the command, args and options passed
to the spawn
invocation. It can inspect these to return a customized runner
for just that invocation.
It can also return a falsy value to indicate that the default function should be used.
returns a function that can be plugged into child_process
as a replacement
for spawn
returns a runner function that exits with the specified code and writes specific data to the output and error streams
Arguments are:
sets the default processing of all spawn invocations to use the runner function specified
enables the sequence
strategy and calls the runner function supplied at the
specific point in the sequence.
add
plugs a runner function
for the nth invocation to spawn
Do not mix sequence.add
and setStrategy
calls for a specific run.
sets fn
as the strategy that will return runner functions on demand.
Do not mix sequence.add
and setStrategy
calls for a specific run.
sets obj
as a lookup table for whether to exit. If the value is true
,
then the runner will emit exit
with code null
and signal <signal>
.
array of mock process objects that you can use to inspect how your library
under test invoked spawn
. Every object has the following properties available
command
- the commandargs
- the command argumentsopts
- the options passed to the spawn invocationexitCode
- the exit code of the processsignal
- the signal delivered to the process (simulated via the runner)BSD. See accompanying LICENSE file.
The following third-party libraries are used by this module:
Pull requests welcome!
child_process.fork
and child_process.exec
processingprocess.kill
FAQs
A mock for child_process.spawn
We found that mock-spawn 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.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.