New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

better-npm-audit

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

better-npm-audit - npm Package Compare versions

Comparing version 1.8.1 to 1.9.0

.eslintrc.js

58

index.js

@@ -11,3 +11,4 @@ #!/usr/bin/env node

const { isWholeNumber, mapLevelToNumber, getVulnerabilities, filterValidException } = require('./utils/common');
const { readFile } = require('./utils/file')
const { readFile } = require('./utils/file');
const consoleUtil = require('./utils/console');

@@ -19,4 +20,6 @@ const EXCEPTION_FILE_PATH = '.nsprc';

const MAX_BUFFER_SIZE = 1024 * 1000 * 50; // 50 MB
const SUCCESS_MESSAGE = '🤝 All good!';
const LOGS_EXCEEDED_MESSAGE = '[MAXIMUM EXCEEDED] Logs exceeded the maximum length limit. Add the flag `-f` to see the full audit logs.';
const RESPONSE_MESSAGE = {
SUCCESS: '🤝 All good!',
LOGS_EXCEEDED: '[MAXIMUM EXCEEDED] Logs exceeded the maximum length limit. Add the flag `-f` to see the full audit logs.',
};

@@ -30,7 +33,8 @@ /**

if (vulnerabilities.length > 0) {
const message = `${vulnerabilities.length} vulnerabilities found. Node security advisories: ${vulnerabilities}`;
throw new Error(message);
consoleUtil.error(`${vulnerabilities.length} vulnerabilities found. Node security advisories: ${vulnerabilities}`);
// Exit failed
process.exit(1);
} else {
// Happy happy, joy joy
console.info(SUCCESS_MESSAGE);
consoleUtil.info(RESPONSE_MESSAGE.SUCCESS);
}

@@ -47,14 +51,14 @@ }

if (fullLog) {
console.info(data);
consoleUtil.info(data);
} else {
const toDisplay = data.substring(0, maxLength);
console.info(toDisplay);
consoleUtil.info(toDisplay);
// Display additional info if it is not the full message
if (toDisplay.length < data.length) {
console.info('');
console.info('...');
console.info('');
console.info(LOGS_EXCEEDED_MESSAGE);
console.info('');
consoleUtil.info('');
consoleUtil.info('...');
consoleUtil.info('');
consoleUtil.info(RESPONSE_MESSAGE.LOGS_EXCEEDED);
consoleUtil.info('');
}

@@ -88,3 +92,4 @@ }

* @param {Boolean} fullLog True if the full log should be displayed in the case of no vulerabilities
*/
* @param {Array} exceptionIds List of vulernability IDs to ignore
*/
function audit(auditCommand, auditLevel, fullLog, exceptionIds) {

@@ -130,3 +135,2 @@ // Execute `npm audit` command to get the security report, taking into account

}
if (options && options.ignore) {

@@ -136,15 +140,11 @@ const cmdExceptions = options.ignore.split(SEPARATOR).filter(isWholeNumber).map(Number);

}
if (Array.isArray(exceptionIds) && exceptionIds.length) {
console.info('Exception vulnerabilities ID(s): ', exceptionIds);
consoleUtil.info('Exception vulnerabilities ID(s): ', exceptionIds);
}
if (options && options.level) {
auditLevel = mapLevelToNumber(options.level);
}
if (options && options.production) {
auditCommand += ' --production';
}
if (options && options.full) {

@@ -160,9 +160,9 @@ fullLog = true;

program
.command('audit')
.description('execute npm audit')
.option('-i, --ignore <ids>', 'Vulnerabilities ID(s) to ignore')
.option('-f, --full', `Display the full audit logs. Default to ${DEFAULT_MESSSAGE_LIMIT} characters.`)
.option('-l, --level <auditLevel>', 'The minimum audit level to include')
.option('-p, --production', 'Skip checking devDependencies')
.action(userOptions => handleUserInput(userOptions, audit));
.command('audit')
.description('execute npm audit')
.option('-i, --ignore <ids>', 'Vulnerabilities ID(s) to ignore')
.option('-f, --full', `Display the full audit logs. Default to ${DEFAULT_MESSSAGE_LIMIT} characters.`)
.option('-l, --level <auditLevel>', 'The minimum audit level to include')
.option('-p, --production', 'Skip checking devDependencies')
.action(userOptions => handleUserInput(userOptions, audit));

@@ -176,4 +176,4 @@ program.parse(process.argv);

BASE_COMMAND,
SUCCESS_MESSAGE,
LOGS_EXCEEDED_MESSAGE,
SUCCESS_MESSAGE: RESPONSE_MESSAGE.SUCCESS,
LOGS_EXCEEDED_MESSAGE: RESPONSE_MESSAGE.LOGS_EXCEEDED,
};
{
"name": "better-npm-audit",
"version": "1.8.1",
"version": "1.9.0",
"author": "Jee Mok <jee.ict@hotmail.com>",

@@ -40,6 +40,9 @@ "description": "Made to allow skipping certain vulnerabilities, and any extra handling that are not supported by the default npm audit in the future.",

"scripts": {
"test": "mocha test/index.js"
"test": "mocha test/index.js",
"lint": "eslint ."
},
"devDependencies": {
"chai": "^4.3.0",
"eslint": "^7.25.0",
"eslint-config-google": "^0.14.0",
"mocha": "^8.3.0",

@@ -46,0 +49,0 @@ "sinon": "^9.2.4"

@@ -8,5 +8,32 @@ const sinon = require('sinon');

const V7_JSON_BUFFER_EMPTY = require('./__mocks__/v7-json-buffer-empty.json');
const consoleUtil = require('../utils/console');
const { isWholeNumber, mapLevelToNumber, getVulnerabilities, isJsonString, filterValidException } = require('../utils/common');
const { handleLogDisplay, handleFinish, handleUserInput, BASE_COMMAND, SUCCESS_MESSAGE, LOGS_EXCEEDED_MESSAGE } = require('../index');
const { FG_WHITE, BG_BLACK, RESET_COLOR } = consoleUtil;
describe('console utils', () => {
it('should wrap error console message with styling format correctly', () => {
const stub = sinon.stub(console, 'error');
const message = 'console message';
expect(stub.called).to.equal(false);
consoleUtil.error(message);
expect(stub.called).to.equal(true);
expect(stub.calledWith(`${FG_WHITE}${BG_BLACK}${message}${RESET_COLOR}`)).to.equal(true);
});
it('should wrap error info message with styling format correctly', () => {
const stub = sinon.stub(console, 'info');
const message = 'console message';
expect(stub.called).to.equal(false);
consoleUtil.info(message);
expect(stub.called).to.equal(true);
expect(stub.calledWith(`${FG_WHITE}${message}${RESET_COLOR}`)).to.equal(true);
});
});
describe('common utils', () => {

@@ -32,3 +59,3 @@ it('should return true for valid JSON object', () => {

expect(isWholeNumber(2920)).to.equal(true);
expect(isWholeNumber(0934)).to.equal(true);
expect(isWholeNumber(934)).to.equal(true);
expect(isWholeNumber('0920')).to.equal(true);

@@ -55,10 +82,10 @@

const exceptions = {
137: {
'137': {
ignore: true,
reason: 'Ignored since we dont use xxx method',
},
581: {
'581': {
reason: 'Ignored since we dont use xxx method',
},
980: 'Ignored since we dont use xxx method',
'980': 'Ignored since we dont use xxx method',
'invalid': 'Ignored since we dont use xxx method',

@@ -72,11 +99,11 @@ };

const exceptions = {
137: {
'137': {
ignore: true,
expiry: 1615462130000,
},
581: {
'581': {
ignore: true,
expiry: 1615462140000,
},
980: {
'980': {
ignore: true,

@@ -88,3 +115,2 @@ expiry: 1615462150000,

expect(filterValidException(exceptions)).to.deep.equal([]);
let clock = sinon.stub(Date, 'now').returns(1615462140000);

@@ -227,3 +253,3 @@

it('should be able to handle the success result properly', () => {
const stub = sinon.stub(console, 'info');
const stub = sinon.stub(consoleUtil, 'info');
const vulnerabilities = [];

@@ -239,8 +265,23 @@

it('should be able to handle the found vulnerabilities properly', () => {
const stubProcess = sinon.stub(process, 'exit');
const stubConsole = sinon.stub(consoleUtil, 'error');
const vulnerabilities = [1165, 1890];
expect(() => handleFinish(vulnerabilities)).to.throw('2 vulnerabilities found. Node security advisories: 1165,1890');
expect(stubProcess.called).to.equal(false);
expect(stubConsole.called).to.equal(false);
handleFinish(vulnerabilities);
expect(stubProcess.called).to.equal(true);
expect(stubConsole.called).to.equal(true);
expect(stubProcess.calledWith(1)).to.equal(true);
expect(stubConsole.calledWith('2 vulnerabilities found. Node security advisories: 1165,1890')).to.equal(true);
stubProcess.restore();
stubConsole.restore();
});
it('should be able to handle normal log display correctly', () => {
const stub = sinon.stub(console, 'info');
const stub = sinon.stub(consoleUtil, 'info');
const data = '123456789';

@@ -258,3 +299,3 @@ const fullLog = true;

it('should be able to handle overlength log display properly', () => {
const stub = sinon.stub(console, 'info');
const stub = sinon.stub(consoleUtil, 'info');
const data = '123456789';

@@ -275,3 +316,3 @@ const fullLog = false;

it('should be able to handle log display properly', () => {
const stub = sinon.stub(console, 'info');
const stub = sinon.stub(consoleUtil, 'info');
const data = '123456789';

@@ -278,0 +319,0 @@ const fullLog = false;

@@ -6,3 +6,3 @@ const get = require('lodash.get');

* @param {String} auditLevel The npm audit level
* @return {Number} The numeric value, higher is more severe
* @return {Number} Returns the numeric value, higher is more severe
*/

@@ -31,2 +31,3 @@ function mapLevelToNumber(auditLevel) {

* @param {Array} exceptionIds List of exception vulnerabilities
* @return {Array} Returns the list of found vulnerabilities
*/

@@ -42,5 +43,5 @@ function getVulnerabilities(jsonBuffer = '', auditLevel = 0, exceptionIds = []) {

return Object.values(advisories)
.filter(advisory => mapLevelToNumber(advisory.severity) >= auditLevel) // Filter out if there is requested audit level
.map(advisory => advisory.id) // Map out the vulnerabilities IDs
.filter(id => !exceptionIds.includes(id)); // Filter out exceptions provided by user
.filter(advisory => mapLevelToNumber(advisory.severity) >= auditLevel) // Filter out if there is requested audit level
.map(advisory => advisory.id) // Map out the vulnerabilities IDs
.filter(id => !exceptionIds.includes(id)); // Filter out exceptions provided by user
}

@@ -51,11 +52,11 @@

return Object.values(vulnerabilities)
.filter(vulnerability => mapLevelToNumber(vulnerability.severity) >= auditLevel) // Filter out if there is requested audit level
// Map out the vulnerabilities IDs
.reduce((acc, vulnerability) => {
// Its stored inside `via` array, but sometimes it might be a String
const cleanedArray = get(vulnerability, 'via', []).map(each => get(each, 'source')).filter(Boolean);
// Compile into a single array
return acc.concat(cleanedArray);
}, [])
.filter(id => !exceptionIds.includes(id)); // Filter out exceptions provided by user
.filter(vulnerability => mapLevelToNumber(vulnerability.severity) >= auditLevel) // Filter out if there is requested audit level
// Map out the vulnerabilities IDs
.reduce((acc, vulnerability) => {
// Its stored inside `via` array, but sometimes it might be a String
const cleanedArray = get(vulnerability, 'via', []).map(each => get(each, 'source')).filter(Boolean);
// Compile into a single array
return acc.concat(cleanedArray);
}, [])
.filter(id => !exceptionIds.includes(id)); // Filter out exceptions provided by user
}

@@ -69,3 +70,3 @@

* @param {Object} fileException The exception object
* @return {Array} The list of found
* @return {Array} Returns the list of found vulnerabilities
*/

@@ -86,3 +87,3 @@ function filterValidException(fileException) {

}
// `ignore` flag has to be true
// `ignore` flag has to be true
if (!details.ignore) {

@@ -105,2 +106,6 @@ return acc;

/**
* @param {Any} value The input number
* @return {Boolean} Returns true if the input is a whole number
*/
function isWholeNumber(value) {

@@ -113,2 +118,6 @@ if (!Number(value)) {

/**
* @param {String} string The JSON stringified object
* @return {Boolean} Returns true if the input string is parse-able
*/
function isJsonString(string) {

@@ -121,3 +130,3 @@ try {

return true;
};
}

@@ -124,0 +133,0 @@ module.exports = {

const fs = require('fs');
const { isJsonString } = require('./common');
/**
* @param {String} path The file path
* @return {(Object|Boolean)} Returns the parsed data if found, or else returns `false`
*/
function readFile(path) {

@@ -5,0 +9,0 @@ try {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc