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.
NEL
is an npm module for running
Node.js REPL sessions.
NEL
is a spin-off library from
IJavascript. This fact explains some
of the design decisions in NEL
, such as returning results in MIME format, and
the functionality provided for completion and inspection of Javascript
expressions. See the section on usage for more details.
NEL
is used by the following Jupyter kernels:
Node.js
session. The result can be formatted
as:
HTML
, SVG
, PNG
...)NEL v1.1.0
: New API (added $$.clear({wait}))NEL v1.0.0
: Stable APINEL v0.5.6
: New API (added $$.input() and onRequest callback)NEL v0.5.5
: Accept Promises as outputNEL v0.5.4
: New API (added $$.display() and onDisplay callback)NEL v0.5
: New API (added transpile option)NEL v0.4
: New API (added onStdout and onStderr callbacks)NEL v0.3
: New API (simplify API by hiding type module:nel~Task)NEL v0.2
: API change (removed Session#executionCount)NEL v0.1.1
: New experimental $$mimer$$
and $$defaultMimer$$
NEL v0.1
: Output change (changed function output)NEL v0.0
: Initial releasenpm install nel
The documentation generated by JSDoc can be found here.
// Load `nel` module
var nel = require("nel");
// Setup a new Javascript session
var session = new nel.Session();
// Example of an execution request
// Output:
// { mime: { 'text/plain': '\'Hello, World!\'' } }
var code = "['Hello', 'World!'].join(', ');";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
});
// Example of throwing an exception
// Output:
// { error:
// { ename: 'Error',
// evalue: 'Hello, World!',
// traceback:
// [ 'Error: Hello, World!',
// ' at evalmachine.<anonymous>:1:7',
// ' at run ([eval]:182:19)',
// ' at onMessage ([eval]:63:41)',
// ' at process.EventEmitter.emit (events.js:98:17)',
// ' at handleMessage (child_process.js:318:10)',
// ' at Pipe.channel.onread (child_process.js:345:11)' ] } }
code = "throw new Error('Hello, World!');";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
});
stdout
and stderr
// Example of use of console.log()
// Output:
// Hello, World!
//
// { mime: { 'text/plain': 'undefined' } }
code = "console.log('Hello, World!');";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
onStdout: console.log,
onStderr: console.error,
});
onDisplay
callbackThe Jupyter messaging protocol
introduces the concept of display. A display is very much like an execution
result. It is associated with an execution request and in protocol version 5.1
and above it can be assigned an ID for subsequent updates. Here's an example of
the support provided by NEL
:
// Example using onDisplay callback
// Output:
// { mime: { 'text/plain': 'Hello, World!' } }
code = "$$.display().text('Hello, World!');";
session.execute(code, {
onDisplay: console.log,
});
// Example using a display ID
// Output:
// { display_id: 'test', mime: { 'text/plain': 'Hello, World!' } }
code = "$$.display('test').text('Hello, World!');";
session.execute(code, {
onDisplay: console.log,
});
onRequest
callback and $$.input(options, callback)
The Jupyter messaging protocol
defines an stdin socket, so that a kernel can request an input from the user.
NEL
defines $$.input(options, callback)
to create such a request.
Here are two examples (first one passing a callback to $$.input
; second one
using a Promise
returned by $$.input()
):
// Example passing a callback to $$.input()
// Output:
// { mime: { 'text/plain': '\'opensesame\'' } }
code = "$$.input({prompt:'?', password: true}, function(error, reply) {$$.done(reply)});";
session.execute(code, {
onRequest: function(request, onReply) {
assert(request.input.prompt === "?");
assert(request.input.password === true);
onReply({input: "opensesame"});
},
onSuccess: console.log,
});
// Example using the Promise returned by $$.input()
// Output:
// { mime: { 'text/plain': '\'opensesame\'' } }
code = "(function($$) {$$.input({prompt:'?', password: true}).then($$.done);})($$);";
session.execute(code, {
onRequest: function(request, onReply) {
assert(request.input.prompt === "?");
assert(request.input.password === true);
onReply({input: "opensesame"});
},
onSuccess: console.log,
});
onRequest
callback and $$.clear(options)
The Jupyter messaging protocol
defines the message clear_output
for kernels to request the output of a cell
to be cleared. NEL
provides $$.clear(options)
to implement such a request.
Here's an example showing the use:
// Example using $$.clear(options)
// Output:
// { clear: { wait: true } }
code = "$$.clear({wait: true});";
session.execute(code, {
onRequest: console.log
});
A session may return results in MIME formats other than 'text/plain'.
// HTML example
// Output:
// { mime: { 'text/html': '<div style=\'background-color:olive;width:50px;height:50px\'></div>' } }
code = "$$html$$ = \"<div style='background-color:olive;width:50px;height:50px'></div>\";";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
});
// SVG example
// Output:
// { mime: { 'image/svg+xml': '<svg><rect width=80 height=80 style=\'fill: orange;\'/></svg>' } }
code = "$$svg$$ = \"<svg><rect width=80 height=80 style='fill: orange;'/></svg>\";";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
});
// PNG example
code = "$$png$$ = require('fs').readFileSync('image.png').toString('base64');";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
});
// JPEG example
code = "$$jpeg$$ = require('fs').readFileSync('image.jpg').toString('base64');";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
});
// MIME example
code = "$$mime$$ = {\"text/html\": \"<div style='background-color:olive;width:50px;height:50px'></div>\"};";
session.execute(code, {
onSuccess: console.log,
onError: console.error,
});
When the result of an execution request is a Promise
, NEL
enables
asynchronous execution automatically and waits for the Promise
to resolve:
// Example returning a Promise
// Output:
// { mime: { 'text/plain': '\'Hello, World!\'' } }
code = "Promise.resolve('Hello, World!');";
session.execute(code, {
onSuccess: console.log,
});
NEL
can parse simple Javascript variable expressions and generate a list of
completion options:
session.complete(
"set", // code
3, // cursorPos
{
onSuccess: console.log,
onError: console.error,
}
);
// Output:
// { completion:
// { list: [ 'setImmediate', 'setInterval', 'setTimeout' ],
// code: 'set',
// cursorPos: 3,
// matchedText: 'set',
// cursorStart: 0,
// cursorEnd: 3 } }
Note that the cursor position can be located anywhere within the Javascript code:
session.complete(
"set", // code
2, // cursorPos
{
onSuccess: console.log,
onError: console.error,
}
);
// Output:
// { completion:
// { list: [ 'setImmediate', 'setInterval', 'setTimeout' ],
// code: 'set',
// cursorPos: 2,
// matchedText: 'se',
// cursorStart: 0,
// cursorEnd: 3 } }
NEL
can parse simple Javascript variable expressions and inspect their value:
code = "var a = [1, 2, 3];";
session.execute(code, null, onError);
session.inspect(
code, // code
5, // cursorPos
{
onSuccess: console.log,
onError: console.error,
}
);
// Output:
// { inspection:
// { string: '[ 1, 2, 3 ]',
// type: 'Array',
// constructorList: [ 'Array', 'Object' ],
// length: 3,
// code: 'var a = [1, 2, 3];',
// cursorPos: 5,
// matchedText: 'a' } }
NEL
can also provide relevant documentation (currently only available for
Javascript builtins):
session.inspect(
"parseInt", // code
8, // cursorPos
{
onSuccess: console.log,
onError: console.error,
}
);
// Output:
// { inspection:
// { string: '[Function: parseInt]',
// type: 'Object',
// constructorList: [ 'Function', 'Object' ],
// length: 2,
// code: 'parseInt',
// cursorPos: 8,
// matchedText: 'parseInt' },
// doc:
// { description: 'The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).',
// url: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt',
// usage: 'parseInt(string, radix);' } }
beforeRun
and afterRun
var beforeRun = function() { console.log("This callback runs first"); }
code = "'I run next'";
var afterRun = function() { console.log("This callback runs last"); }
session.execute(code, {
onSuccess: console.log,
onError: console.error,
beforeRun: beforeRun,
afterRun: afterRun,
});
// Output:
// This callback runs first
// { mime: { 'text/plain': '\'I run next\'' } }
// This callback runs last
First of all, thank you for taking the time to contribute. Please, read CONTRIBUTING.md and use the issue tracker for any contributions: support requests, bug reports, enhancement requests, pull requests, ...
Node.js
documentationFAQs
Node.js Evaluation Loop (NEL): module to run a Node.js REPL session
The npm package nel receives a total of 351 weekly downloads. As such, nel popularity was classified as not popular.
We found that nel 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.