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.
eslint-ast-utils
Advanced tools
Utility library to manipulate ASTs for ESLint projects
$ npm install --save eslint-ast-utils
const astUtils = require('eslint-ast-utils');
Checks whether node
is a call to CommonJS's require
function.
Returns true
if and only if:
node
is a CallExpression
node
's callee is an Identifier
named require
node
has exactly 1 Literal
argument whose value is a string
Example:
require('lodash');
// => true
require(foo);
// => false
foo('lodash');
// => false
Usage example:
function create(context) {
return {
CallExpression(node) {
if (astUtils.isStaticRequire(node)) {
context.report({
node: node,
message: 'Use import syntax rather than `require`'
});
}
}
};
}
Gets the source of a require()
call. If node
is not a require
call (in the definition of isStaticRequire
), it will return undefined
.
Example:
require('lodash');
// => 'lodash'
require('./foo');
// => './foo'
Usage example:
function create(context) {
return {
CallExpression(node) {
if (astUtils.isStaticRequire(node) && astUtils.getRequireSource(node) === 'underscore') {
context.report({
node: node,
message: 'Use `lodash` instead of `underscore`'
});
}
}
};
}
Checks if there is a reference to a variable named name
inside of node
.
Returns true if and only if:
Identifier
named name
inside of node
Identifier
is a variable (i.e. not a static property name for instance)Identifier
does not reference a different variable named name
introduced in a sub-scope of node
.Example:
foo(a);
// containsIdentifier('a', node) // => true
// containsIdentifier('b', node) // => true
function foo(fn) {
return function(a) {
return fn(a);
};
}
// containsIdentifier('a', node) // => false
Usage example:
function create(context) {
return {
FunctionDeclaration(node) {
node.params.forEach(param => {
if (param.type === 'Identifier' && !astUtils.containsIdentifier(param.name, node.body)) {
context.report({
node: node,
message: `${name} is never used`
});
}
});
}
};
}
Checks if there is a reference to a variable named name
inside any node of the nodes
array. Will return false
if nodes
is not an array.
This is a shorthand version of containsIdentifier
that works for arrays. The following are equivalent:
[node1, node2, node3].some(node => astUtils.containsIdentifier('a', node));
// equivalent to
astUtils.someContainIdentifier('a', [node1, node2, node3]);
Get the name of a MemberExpression
's property. Returns:
string
if the property is accessed through dot notation.string
if the property is accessed through brackets and is a string.number
if the property is accessed through brackets and is a number.undefined
if node
is not a MemberExpression
undefined
if the property name is a hard to compute expression.Example:
foo.bar
// => 'bar'
foo['bar']
// => 'bar'
foo[bar]
// => undefined
foo[0]
// => 0 # Number
foo[null]
// => null
foo[undefined]
// => undefined
Usage example:
function create(context) {
return {
MemberExpression(node) {
if (astUtils.getPropertyName(node).startsWith('_')) {
context.report({
node: node,
message: 'Don\'t access "private" fields'
});
}
}
};
}
Get the value of an expression that can be statically computed, i.e. without variables references or expressions too complex.
Returns:
undefined
if the value could not be statically computed.value
property containing the computed value.Example:
foo
// => undefined
42
// => {value: 42}
'foo'
// => {value: 'foo'}
undefined
// => {value: undefined}
null
// => {value: null}
1 + 2 - 4 + (-1)
// => {value: -2}
true ? 1 : 2
// => {value: 1}
`foo ${'bar'}`
// => {value: 'foo bar'}
Usage example:
function create(context) {
return {
TemplateLiteral(node) {
const expression = astUtils.computeStaticExpression(node);
if (expression) {
context.report({
node: node,
message: `You can replace this template literal by the regular string '${expression.value}'.`
});
}
}
};
}
Checks whether node
is a Promise.
Returns true
if and only if node
is one of the following:
then
or catch
propertiesPromise
(except cancel
, promisify
, promisifyAll
and is
)new Promise
If node
uses unknown properties of a value that would be considered a Promise, node
itself would not be considered as a Promise.
Example:
foo.then(fn);
// => true
foo.catch(fn);
// => true
foo.then(fn).catch(fn);
// => true
foo.then(fn).isFulfilled(fn); // isFulfilled(fn) may not return a Promise
// => false
Promise.resolve(value);
// => true
Promise.reject(value);
// => true
Promise.race(promises);
// => true
Promise.all(promises);
// => true
Promise.map(promises, fn); // Bluebird method
// => true
new Promise(fn);
// => true
new Promise.resolve(value);
// => false
Usage example:
function create(context) {
function reportIfPromise(node) {
if (astUtils.isPromise(node)) {
context.report({
node: node,
message: 'Prefer using async/await'
});
}
}
return {
CallExpression: reportIfPromise,
NewExpression: reportIfPromise
};
}
Checks whether node
is a function expression or an arrow function expression (not a function declaration).
If node
uses unknown properties of a value that would be considered a Promise, node
itself would not be considered as a Promise.
Example:
(function foo() {})
// => true
() => {}
// => true
function foo() {} // function declaration
// => false
Usage example:
function create(context) {
return {
CallExpression(node) {
if (node.callee.type === 'Identifier'
&& node.callee.name === 'test'
&& !astUtils.isFunctionExpression(node.arguments[0])
&& !astUtils.isFunctionExpression(node.arguments[1])
) {
context.report({
node: node,
message: 'You need to pass a function to test()'
});
}
}
};
}
MIT © Jeroen Engels
FAQs
Utility library to manipulate ASTs
We found that eslint-ast-utils 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.