Socket
Socket
Sign inDemoInstall

audit-ci

Package Overview
Dependencies
Maintainers
2
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

audit-ci - npm Package Compare versions

Comparing version 2.5.1 to 3.0.0

lib/colors.js

13

lib/audit-ci-version.js

@@ -1,10 +0,15 @@

const { version: auditCiVersion } = require('../package.json');
const { bugs, version: auditCiVersion } = require("../package.json");
const { yellow } = require("./colors");
if (!auditCiVersion) {
console.log(
'\x1b[33m%s\x1b[0m',
'Could not identify audit-ci version. Please report this issue to https://github.com/IBM/audit-ci/issues.'
yellow,
`Could not identify audit-ci version. Please report this issue to ${bugs}.`
);
}
module.exports = { auditCiVersion };
function printAuditCiVersion() {
console.log(`audit-ci version: ${auditCiVersion}`);
}
module.exports = { auditCiVersion, printAuditCiVersion };

@@ -6,104 +6,109 @@ /*

*/
const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const fs = require("fs");
const path = require("path");
const yargs = require("yargs");
const audit = require("./audit");
const { printAuditCiVersion } = require("./audit-ci-version");
const { green, red } = require("./colors");
printAuditCiVersion();
const { argv } = yargs
.config('config')
.config("config")
.options({
l: {
alias: 'low',
alias: "low",
default: false,
describe: 'Exit for low vulnerabilities or higher',
type: 'boolean',
describe: "Exit for low vulnerabilities or higher",
type: "boolean",
},
m: {
alias: 'moderate',
alias: "moderate",
default: false,
describe: 'Exit for moderate vulnerabilities or higher',
type: 'boolean',
describe: "Exit for moderate vulnerabilities or higher",
type: "boolean",
},
h: {
alias: 'high',
alias: "high",
default: false,
describe: 'Exit for high vulnerabilities or higher',
type: 'boolean',
describe: "Exit for high vulnerabilities or higher",
type: "boolean",
},
c: {
alias: 'critical',
alias: "critical",
default: false,
describe: 'Exit for critical vulnerabilities',
type: 'boolean',
describe: "Exit for critical vulnerabilities",
type: "boolean",
},
p: {
alias: 'package-manager',
default: 'auto',
describe: 'Choose a package manager',
choices: ['auto', 'npm', 'yarn'],
alias: "package-manager",
default: "auto",
describe: "Choose a package manager",
choices: ["auto", "npm", "yarn"],
},
r: {
alias: 'report',
alias: "report",
default: false,
describe: 'Show a full audit report',
type: 'boolean',
describe: "Show a full audit report",
type: "boolean",
},
s: {
alias: 'summary',
alias: "summary",
default: false,
describe: 'Show a summary audit report',
type: 'boolean',
describe: "Show a summary audit report",
type: "boolean",
},
a: {
alias: 'advisories',
alias: "advisories",
default: [],
describe: 'Whitelisted advisory ids',
type: 'array',
describe: "Whitelisted advisory ids",
type: "array",
},
w: {
alias: 'whitelist',
alias: "whitelist",
default: [],
describe: 'Whitelisted module names',
type: 'array',
describe: "Whitelisted module names",
type: "array",
},
d: {
alias: 'directory',
default: './',
describe: 'The directory containing the package.json to audit',
type: 'string',
alias: "directory",
default: "./",
describe: "The directory containing the package.json to audit",
type: "string",
},
'show-not-found': {
"show-not-found": {
default: true,
describe: 'Show whitelisted advisories that are not found',
type: 'boolean',
describe: "Show whitelisted advisories that are not found",
type: "boolean",
},
registry: {
default: undefined,
describe: 'The registry to resolve packages by name and version',
type: 'string',
describe: "The registry to resolve packages by name and version",
type: "string",
},
'report-type': {
default: 'important',
describe: 'Format for the audit report results',
type: 'string',
choices: ['important', 'summary', 'full'],
"report-type": {
default: "important",
describe: "Format for the audit report results",
type: "string",
choices: ["important", "summary", "full"],
},
'retry-count': {
"retry-count": {
default: 5,
describe:
'The number of attempts audit-ci calls an unavailable registry before failing',
type: 'number',
"The number of attempts audit-ci calls an unavailable registry before failing",
type: "number",
},
'pass-enoaudit': {
"pass-enoaudit": {
default: false,
describe:
'Pass if no audit is performed due to the registry returning ENOAUDIT',
type: 'boolean',
"Pass if no audit is performed due to the registry returning ENOAUDIT",
type: "boolean",
},
'path-whitelist': {
"path-whitelist": {
default: [],
describe: 'Whitelisted vulnerability paths',
type: 'array',
describe: "Whitelisted vulnerability paths",
type: "array",
},
})
.help('help');
.help("help");

@@ -127,21 +132,7 @@ function mapVulnerabilityLevelInput(config) {

function mapReportTypeInput(config) {
const { 'report-type': reportType, report, summary } = config;
if (report) {
console.warn(
'\x1b[33m%s\x1b[0m',
"[DEPRECATED] The 'r' and 'report' options have been deprecated and may be removed in the future. Use `--report-type important` [default] to show only relevant information or `--report-type full` to show the full audit report."
);
return 'full';
}
if (summary) {
console.warn(
'\x1b[33m%s\x1b[0m',
"[DEPRECATED] The 's' and 'summary' options have been deprecated and may be removed in the future. Use `--report-type important` [default] to show only relevant information or `--report-type summary` to show only the audit metadata."
);
return 'summary';
}
const { "report-type": reportType } = config;
switch (reportType) {
case 'full':
case 'important':
case 'summary':
case "full":
case "important":
case "summary":
return reportType;

@@ -156,3 +147,3 @@ default:

argv.levels = mapVulnerabilityLevelInput(argv);
argv['report-type'] = mapReportTypeInput(argv);
argv["report-type"] = mapReportTypeInput(argv);

@@ -166,16 +157,15 @@ /**

switch (pmArg) {
case 'npm':
return 'npm';
case 'yarn':
return 'yarn';
case 'auto': {
const getPath = file => path.resolve(directory, file);
const packageLockExists = fs.existsSync(getPath('package-lock.json'));
if (packageLockExists) return 'npm';
const shrinkwrapExists = fs.existsSync(getPath('npm-shrinkwrap.json'));
if (shrinkwrapExists) return 'npm';
const yarnLockExists = fs.existsSync(getPath('yarn.lock'));
if (yarnLockExists) return 'yarn';
case "npm":
case "yarn":
return pmArg;
case "auto": {
const getPath = (file) => path.resolve(directory, file);
const packageLockExists = fs.existsSync(getPath("package-lock.json"));
if (packageLockExists) return "npm";
const shrinkwrapExists = fs.existsSync(getPath("npm-shrinkwrap.json"));
if (shrinkwrapExists) return "npm";
const yarnLockExists = fs.existsSync(getPath("yarn.lock"));
if (yarnLockExists) return "yarn";
throw Error(
'Cannot establish package-manager type, missing package-lock.json and yarn.lock.'
"Cannot establish package-manager type, missing package-lock.json and yarn.lock."
);

@@ -190,11 +180,12 @@ }

require('./audit')(pm, argv)
.then(() => {
console.log('\x1b[32m%s\x1b[0m', `Passed ${pm} security audit.`);
})
.catch(err => {
(async () => {
try {
await audit(pm, argv);
console.log(green, `Passed ${pm} security audit.`);
} catch (err) {
const message = err.message || err;
console.error('\x1b[31m%s\x1b[0m', message);
console.error('\x1b[31m%s\x1b[0m', 'Exiting...');
console.error(red, message);
console.error(red, "Exiting...");
process.exitCode = 1;
});
}
})();

@@ -1,36 +0,41 @@

const npmAuditer = require('./npm-auditer');
const yarnAuditer = require('./yarn-auditer');
const { yellow } = require("./colors");
const npmAuditer = require("./npm-auditer");
const yarnAuditer = require("./yarn-auditer");
const PARTIAL_RETRY_ERROR_MSG = {
// The three ENOAUDIT error messages for NPM are:
// `Either your login credentials are invalid or your registry (${opts.registry}) does not support audit.`
// `Your configured registry (${opts.registry}) does not support audit requests.`
// `Your configured registry (${opts.registry}) may not support audit requests, or the audit endpoint may be temporarily unavailable.`
// Between them, all three use the phrasing 'not support audit'.
npm: `not support audit`,
yarn: "503 Service Unavailable",
};
function audit(pm, config, reporter) {
const auditor = pm === 'npm' ? npmAuditer : yarnAuditer;
const PARTIAL_RETRY_ERROR_MSG = {
// The three ENOAUDIT error messages for NPM are:
// `Either your login credentials are invalid or your registry (${opts.registry}) does not support audit.`
// `Your configured registry (${opts.registry}) does not support audit requests.`
// `Your configured registry (${opts.registry}) may not support audit requests, or the audit endpoint may be temporarily unavailable.`
// Between them, all three use the phrasing 'not support audit'.
npm: `not support audit`,
yarn: '503 Service Unavailable',
};
const auditor = pm === "npm" ? npmAuditer : yarnAuditer;
const {
"pass-enoaudit": passENoAudit,
"retry-count": maxRetryCount,
} = config;
function run(attempt = 0) {
return auditor.audit(config, reporter).catch(err => {
async function run(attempt = 0) {
try {
const result = await auditor.audit(config, reporter);
return result;
} catch (err) {
const message = err.message || err;
if (
attempt < config['retry-count'] &&
message &&
message.includes(PARTIAL_RETRY_ERROR_MSG[pm])
) {
console.log('RETRY-RETRY');
const isRetryableMessage =
typeof message === "string" &&
message.includes(PARTIAL_RETRY_ERROR_MSG[pm]);
const shouldRetry = attempt < maxRetryCount && isRetryableMessage;
if (shouldRetry) {
console.log("RETRY-RETRY");
return run(attempt + 1);
}
if (
config['pass-enoaudit'] &&
message.includes(PARTIAL_RETRY_ERROR_MSG[pm])
) {
const shouldPassWithoutAuditing = passENoAudit && isRetryableMessage;
if (shouldPassWithoutAuditing) {
console.warn(
'\x1b[33m%s\x1b[0m',
`ACTION RECOMMENDED: An audit could not performed due to ${
config['retry-count']
} audits that resulted in ENOAUDIT. Perform an audit manually and verify that no significant vulnerabilities exist before merging.`
yellow,
`ACTION RECOMMENDED: An audit could not performed due to ${maxRetryCount} audits that resulted in ENOAUDIT. Perform an audit manually and verify that no significant vulnerabilities exist before merging.`
);

@@ -40,3 +45,3 @@ return Promise.resolve();

throw err;
});
}
}

@@ -43,0 +48,0 @@

@@ -6,25 +6,23 @@ /*

*/
const { spawn } = require('cross-spawn');
const eventStream = require('event-stream');
const JSONStream = require('JSONStream');
const ReadlineTransform = require('readline-transform');
const { spawn } = require("cross-spawn");
const eventStream = require("event-stream");
const JSONStream = require("JSONStream");
const ReadlineTransform = require("readline-transform");
const { blue, yellow } = require("./colors");
function reportAudit(summary, config) {
const { whitelist, 'show-not-found': showNotFound } = config;
const { whitelist, "show-not-found": showNotFound } = config;
if (whitelist.length) {
console.log(
'\x1b[36m%s\x1b[0m',
'Modules to whitelist: '.concat(whitelist.join(', '), '.')
);
console.log(blue, `Modules to whitelist: ${whitelist.join(", ")}.`);
}
if (summary.whitelistedModulesFound.length) {
const found = summary.whitelistedModulesFound.join(', ');
const found = summary.whitelistedModulesFound.join(", ");
const msg = `Vulnerable whitelisted modules found: ${found}.`;
console.warn('\x1b[33m%s\x1b[0m', msg);
console.warn(yellow, msg);
}
if (summary.whitelistedAdvisoriesFound.length) {
const found = summary.whitelistedAdvisoriesFound.join(', ');
const found = summary.whitelistedAdvisoriesFound.join(", ");
const msg = `Vulnerable whitelisted advisories found: ${found}.`;
console.warn('\x1b[33m%s\x1b[0m', msg);
console.warn(yellow, msg);
}

@@ -34,5 +32,5 @@ if (showNotFound && summary.whitelistedAdvisoriesNotFound.length) {

.sort((a, b) => a - b)
.join(', ');
.join(", ");
const msg = `Vulnerable whitelisted advisories not found: ${found}.\nConsider not whitelisting them.`;
console.warn('\x1b[33m%s\x1b[0m', msg);
console.warn(yellow, msg);
}

@@ -43,5 +41,5 @@

const err = `Failed security audit due to ${summary.failedLevelsFound.join(
', '
", "
)} vulnerabilities.\nVulnerable advisories are: ${summary.advisoriesFound.join(
', '
", "
)}`;

@@ -54,21 +52,20 @@ throw new Error(err);

function runProgram(command, args, options, stdoutListener, stderrListener) {
return new Promise(resolve => {
const proc = spawn(command, args, options);
const transform = new ReadlineTransform({ skipEmpty: true });
proc.stdout.setEncoding('utf8');
proc.stdout
.pipe(transform)
.pipe(JSONStream.parse())
.pipe(
eventStream.mapSync(data => {
if (!data) return;
try {
stdoutListener(data);
} catch (error) {
stderrListener(error);
}
})
);
proc.on('close', () => resolve());
const transform = new ReadlineTransform({ skipEmpty: true });
const proc = spawn(command, args, options);
proc.stdout.setEncoding("utf8");
proc.stdout
.pipe(transform)
.pipe(JSONStream.parse())
.pipe(
eventStream.mapSync((data) => {
if (!data) return;
try {
stdoutListener(data);
} catch (error) {
stderrListener(error);
}
})
);
return new Promise((resolve) => {
proc.on("close", () => resolve());
});

@@ -75,0 +72,0 @@ }

@@ -6,7 +6,8 @@ /*

*/
const SUPPORTED_SEVERITY_LEVELS = new Set()
.add('critical')
.add('high')
.add('moderate')
.add('low');
const SUPPORTED_SEVERITY_LEVELS = new Set([
"critical",
"high",
"moderate",
"low",
]);

@@ -16,8 +17,7 @@ class Model {

const unsupported = Object.keys(config.levels).filter(
curr => !SUPPORTED_SEVERITY_LEVELS.has(curr)
(curr) => !SUPPORTED_SEVERITY_LEVELS.has(curr)
);
unsupported.sort();
if (unsupported.length) {
throw new Error(
`Unsupported severity levels found: ${unsupported.join(', ')}`
`Unsupported severity levels found: ${unsupported.sort().join(", ")}`
);

@@ -28,3 +28,3 @@ }

this.whitelistedModuleNames = config.whitelist;
this.whitelistedPaths = config['path-whitelist'] || [];
this.whitelistedPaths = config["path-whitelist"] || [];
this.whitelistedAdvisoryIds = config.advisories;

@@ -43,3 +43,3 @@

if (this.whitelistedModuleNames.some(m => m === advisory.module_name)) {
if (this.whitelistedModuleNames.some((m) => m === advisory.module_name)) {
if (!this.whitelistedModulesFound.includes(advisory.module_name)) {

@@ -51,3 +51,3 @@ this.whitelistedModulesFound.push(advisory.module_name);

if (this.whitelistedAdvisoryIds.some(a => Number(a) === advisory.id)) {
if (this.whitelistedAdvisoryIds.some((a) => Number(a) === advisory.id)) {
if (!this.whitelistedAdvisoriesFound.includes(advisory.id)) {

@@ -59,4 +59,4 @@ this.whitelistedAdvisoriesFound.push(advisory.id);

advisory.findings.forEach(finding =>
finding.paths.forEach(path => {
advisory.findings.forEach((finding) =>
finding.paths.forEach((path) => {
if (this.whitelistedPaths.includes(`${advisory.id}|${path}`)) {

@@ -69,4 +69,4 @@ this.whitelistedPathsFound.push(`${advisory.id}|${path}`);

if (
advisory.findings.every(finding =>
finding.paths.every(path =>
advisory.findings.every((finding) =>
finding.paths.every((path) =>
this.whitelistedPaths.includes(`${advisory.id}|${path}`)

@@ -83,6 +83,3 @@ )

load(parsedOutput) {
Object.keys(parsedOutput.advisories)
// Get the advisories values (Object.values not supported in Node 6)
.map(k => parsedOutput.advisories[k])
.forEach(a => this.process(a));
Object.values(parsedOutput.advisories).forEach((a) => this.process(a));

@@ -92,5 +89,5 @@ return this.getSummary();

getSummary(advisoryMapper = a => a.id) {
getSummary(advisoryMapper = (a) => a.id) {
const foundSeverities = new Set();
this.advisoriesFound.forEach(curr => foundSeverities.add(curr.severity));
this.advisoriesFound.forEach((curr) => foundSeverities.add(curr.severity));
const failedLevelsFound = [...foundSeverities.values()];

@@ -102,3 +99,3 @@ failedLevelsFound.sort();

const whitelistedAdvisoriesNotFound = this.whitelistedAdvisoryIds.filter(
id => !this.whitelistedAdvisoriesFound.includes(id)
(id) => !this.whitelistedAdvisoriesFound.includes(id)
);

@@ -105,0 +102,0 @@

@@ -6,13 +6,13 @@ /*

*/
const { auditCiVersion } = require('./audit-ci-version');
const { runProgram, reportAudit } = require('./common');
const Model = require('./Model');
const { blue } = require("./colors");
const { runProgram, reportAudit } = require("./common");
const Model = require("./Model");
function runNpmAudit(config) {
async function runNpmAudit(config) {
const { directory, registry, _npm } = config;
const npmExec = _npm || 'npm';
const npmExec = _npm || "npm";
let stdoutBuffer = {};
function outListener(data) {
stdoutBuffer = Object.assign({}, stdoutBuffer, data);
stdoutBuffer = { ...stdoutBuffer, ...data };
}

@@ -25,40 +25,33 @@

const args = ['audit', '--json'];
const args = ["audit", "--json"];
if (registry) {
args.push('--registry', registry);
args.push("--registry", registry);
}
const options = { cwd: directory };
return Promise.resolve()
.then(() => runProgram(npmExec, args, options, outListener, errListener))
.then(() => {
if (stderrBuffer.length) {
throw new Error(
`Invocation of npm audit failed:\n${stderrBuffer.join('\n')}`
);
}
return stdoutBuffer;
});
await runProgram(npmExec, args, options, outListener, errListener);
if (stderrBuffer.length) {
throw new Error(
`Invocation of npm audit failed:\n${stderrBuffer.join("\n")}`
);
}
return stdoutBuffer;
}
function printReport(parsedOutput, levels, reportType) {
function printReportObj(text, obj) {
console.log('\x1b[36m%s\x1b[0m', text);
const printReportObj = (text, obj) => {
console.log(blue, text);
console.log(JSON.stringify(obj, null, 2));
}
console.log(`audit-ci version: ${auditCiVersion}`);
};
switch (reportType) {
case 'full':
printReportObj('Yarn audit report JSON:', parsedOutput);
case "full":
printReportObj("Yarn audit report JSON:", parsedOutput);
break;
case 'important': {
case "important": {
const relevantAdvisories = Object.keys(parsedOutput.advisories).reduce(
(acc, advisory) =>
levels[parsedOutput.advisories[advisory].severity]
? Object.assign(
{ [advisory]: parsedOutput.advisories[advisory] },
acc
)
? {
[advisory]: parsedOutput.advisories[advisory],
...acc,
}
: acc,

@@ -71,7 +64,7 @@ {}

};
printReportObj('NPM audit report results:', keyFindings);
printReportObj("NPM audit report results:", keyFindings);
break;
}
case 'summary':
printReportObj('NPM audit report summary:', parsedOutput.metadata);
case "summary":
printReportObj("NPM audit report summary:", parsedOutput.metadata);
break;

@@ -83,3 +76,2 @@ default:

}
return parsedOutput;
}

@@ -101,20 +93,14 @@

*/
function audit(config, reporter = reportAudit) {
return Promise.resolve()
.then(() => runNpmAudit(config))
.then(parsedOutput => {
if (parsedOutput.error) {
const { code, summary } = parsedOutput.error;
if (code !== 'ENOAUDIT' || !config['pass-enoaudit']) {
throw new Error(`code ${code}: ${summary}`);
}
}
return printReport(parsedOutput, config.levels, config['report-type']);
})
.then(parsedOutput =>
reporter(new Model(config).load(parsedOutput), config, parsedOutput)
);
async function audit(config, reporter = reportAudit) {
const parsedOutput = await runNpmAudit(config);
if (parsedOutput.error) {
const { code, summary } = parsedOutput.error;
throw new Error(`code ${code}: ${summary}`);
}
printReport(parsedOutput, config.levels, config["report-type"]);
const model = new Model(config);
const summary = model.load(parsedOutput);
return reporter(summary, config, parsedOutput);
}
module.exports = { audit };

@@ -6,9 +6,9 @@ /*

*/
const childProcess = require('child_process');
const semver = require('semver');
const { auditCiVersion } = require('./audit-ci-version');
const { reportAudit, runProgram } = require('./common');
const Model = require('./Model');
const childProcess = require("child_process");
const semver = require("semver");
const { blue, red, yellow } = require("./colors");
const { reportAudit, runProgram } = require("./common");
const Model = require("./Model");
const MINIMUM_YARN_VERSION = '1.12.3';
const MINIMUM_YARN_VERSION = "1.12.3";
/**

@@ -19,9 +19,6 @@ * Change this to the appropriate version when

*/
const MINIMUM_YARN_AUDIT_REGISTRY_VERSION = '99.99.99';
const MINIMUM_YARN_AUDIT_REGISTRY_VERSION = "99.99.99";
function getYarnVersion() {
const version = childProcess
.execSync('yarn -v')
.toString()
.replace('\n', '');
const version = childProcess.execSync("yarn -v").toString().replace("\n", "");
return version;

@@ -52,129 +49,130 @@ }

*/
function audit(config, reporter = reportAudit) {
return Promise.resolve().then(() => {
const {
levels,
registry,
'report-type': reportType,
whitelist,
_yarn,
} = config;
const yarnExec = _yarn || 'yarn';
let missingLockFile = false;
const model = new Model(config);
async function audit(config, reporter = reportAudit) {
const {
levels,
registry,
"report-type": reportType,
whitelist,
_yarn,
} = config;
const yarnExec = _yarn || "yarn";
let missingLockFile = false;
const model = new Model(config);
const yarnVersion = getYarnVersion();
const isYarnVersionSupported = yarnSupportsAudit(yarnVersion);
if (!isYarnVersionSupported) {
const yarnVersion = getYarnVersion();
const isYarnVersionSupported = yarnSupportsAudit(yarnVersion);
if (!isYarnVersionSupported) {
throw new Error(
`Yarn ${yarnVersion} not supported, must be >=${MINIMUM_YARN_VERSION}`
);
}
if (whitelist.length) {
console.log(`Modules to whitelist: ${whitelist.join(", ")}.`);
}
switch (reportType) {
case "full":
console.log(blue, "Yarn audit report JSON:");
break;
case "important":
console.log(blue, "Yarn audit report results:");
break;
case "summary":
console.log(blue, "Yarn audit report summary:");
break;
default:
throw new Error(
`Yarn ${yarnVersion} not supported, must be >=${MINIMUM_YARN_VERSION}`
`Invalid report type: ${reportType}. Should be \`['important', 'full', 'summary']\`.`
);
}
}
console.log(`audit-ci version: ${auditCiVersion}`);
if (whitelist.length) {
console.log(`Modules to whitelist: ${whitelist.join(', ')}.`);
}
switch (reportType) {
case 'full':
console.log('\x1b[36m%s\x1b[0m', 'Yarn audit report JSON:');
break;
case 'important':
console.log('\x1b[36m%s\x1b[0m', 'Yarn audit report results:');
break;
case 'summary':
console.log('\x1b[36m%s\x1b[0m', 'Yarn audit report summary:');
break;
default:
throw new Error(
`Invalid report type: ${reportType}. Should be \`['important', 'full', 'summary']\`.`
);
}
function outListener(line) {
try {
const { type, data } = line;
switch (reportType) {
case 'full':
console.log(JSON.stringify(line, null, 2));
break;
case 'important':
if (
(type === 'auditAdvisory' && levels[data.advisory.severity]) ||
type === 'auditSummary'
) {
console.log(JSON.stringify(data, null, 2));
}
break;
case 'summary':
if (type === 'auditSummary') {
console.log(JSON.stringify(data, null, 2));
}
break;
default:
throw new Error(
`Invalid report type: ${reportType}. Should be \`['important', 'full', 'summary']\`.`
);
const printJson = (data) => {
console.log(JSON.stringify(data, null, 2));
};
// Define a function to print based on the report type.
let printAuditData;
switch (reportType) {
case "full":
printAuditData = (line) => {
printJson(line);
};
break;
case "important":
printAuditData = ({ type, data }) => {
if (
(type === "auditAdvisory" && levels[data.advisory.severity]) ||
type === "auditSummary"
) {
printJson(data);
}
if (type === 'info' && data === 'No lockfile found.') {
missingLockFile = true;
return;
};
break;
case "summary":
printAuditData = ({ type, data }) => {
if (type === "auditSummary") {
printJson(data);
}
};
break;
default:
throw new Error(
`Invalid report type: ${reportType}. Should be \`['important', 'full', 'summary']\`.`
);
}
if (type !== 'auditAdvisory') {
return;
}
function outListener(line) {
try {
const { type, data } = line;
printAuditData(line);
model.process(data.advisory);
} catch (err) {
console.error(
'\x1b[31m%s\x1b[0m',
`ERROR: Cannot JSONStream.parse response:`
);
console.error(line);
throw err;
if (type === "info" && data === "No lockfile found.") {
missingLockFile = true;
return;
}
if (type !== "auditAdvisory") {
return;
}
model.process(data.advisory);
} catch (err) {
console.error(red, `ERROR: Cannot JSONStream.parse response:`);
console.error(line);
throw err;
}
}
const stderrBuffer = [];
function errListener(line) {
stderrBuffer.push(line);
const stderrBuffer = [];
function errListener(line) {
stderrBuffer.push(line);
if (line.type === 'error') {
throw new Error(line.data);
}
if (line.type === "error") {
throw new Error(line.data);
}
const options = { cwd: config.directory };
const args = ['audit', '--json'];
if (registry) {
const auditRegistrySupported = yarnAuditSupportsRegistry(yarnVersion);
if (auditRegistrySupported) {
args.push('--registry', registry);
} else {
console.warn(
'\x1b[33m%s\x1b[0m',
'Yarn audit does not support the registry flag yet.'
);
}
}
const options = { cwd: config.directory };
const args = ["audit", "--json"];
if (registry) {
const auditRegistrySupported = yarnAuditSupportsRegistry(yarnVersion);
if (auditRegistrySupported) {
args.push("--registry", registry);
} else {
console.warn(
yellow,
"Yarn audit does not support the registry flag yet."
);
}
return runProgram(yarnExec, args, options, outListener, errListener).then(
() => {
if (missingLockFile) {
console.warn(
'\x1b[33m%s\x1b[0m',
'No yarn.lock file. This does not affect auditing, but it may be a mistake.'
);
}
}
await runProgram(yarnExec, args, options, outListener, errListener);
if (missingLockFile) {
console.warn(
yellow,
"No yarn.lock file. This does not affect auditing, but it may be a mistake."
);
}
const summary = model.getSummary(a => a.id);
return reporter(summary, config);
}
);
});
const summary = model.getSummary((a) => a.id);
return reporter(summary, config);
}
module.exports = { audit };
{
"name": "audit-ci",
"version": "2.5.1",
"version": "3.0.0",
"description": "Audits npm and yarn projects in CI environments",

@@ -33,27 +33,28 @@ "license": "Apache-2.0",

"lint": "eslint -c ./.eslintrc.json **/*.js",
"lint:fix": "eslint -c ./.eslintrc.json **/*.js --fix",
"test": "mocha --exit --timeout 40000 --recursive --reporter spec test/*.js"
},
"engines": {
"node": ">=8"
},
"dependencies": {
"JSONStream": "^1.3.5",
"cross-spawn": "6.0.5",
"cross-spawn": "^7.0.2",
"event-stream": "4.0.1",
"readline-transform": "0.9.0",
"semver": "^6.0.0",
"yargs": "12.0.5"
"readline-transform": "1.0.0",
"semver": "^7.0.0",
"yargs": "^15.0.0"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^5.16.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-config-prettier": "4.1.0",
"eslint-plugin-import": "2.16.0",
"eslint-plugin-prettier": "3.0.1",
"husky": "1.3.1",
"mocha": "^6.1.4",
"prettier": "1.16.4",
"pretty-quick": "1.10.0"
"eslint": "^6.8.0",
"eslint-config-airbnb-base": "^14.1.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-prettier": "^3.1.2",
"husky": "^4.0.0",
"mocha": "^7.0.0",
"prettier": "^2.0.2",
"pretty-quick": "^2.0.1"
},
"resolutions": {
"eslint-utils": "^1.4.1"
},
"husky": {

@@ -60,0 +61,0 @@ "hooks": {

@@ -5,3 +5,3 @@ [![Build Status](https://travis-ci.com/IBM/audit-ci.svg?branch=master)](https://travis-ci.com/IBM/audit-ci)

# Overview
# audit-ci

@@ -11,4 +11,9 @@ This module is intended to be consumed by your favourite continuous integration tool to

# Set up
## Requirements
- Node >= 8
- _(Optional)_ Yarn >= 1.12.3 && Yarn < 2
## Set up
> `npm install --save-dev audit-ci`

@@ -54,3 +59,3 @@

name: update-npm
command: 'sudo npm install -g npm'
command: "sudo npm install -g npm"
- restore_cache:

@@ -60,3 +65,3 @@ key: dependency-cache-{{ checksum "package.json" }}

name: install-npm
command: 'npm install --no-audit'
command: "npm install --no-audit"
# This should run immediately after installation to reduce

@@ -104,4 +109,2 @@ # the risk of executing a script from a compromised NPM package.

| | --config | Path to JSON config file |
| -r | --report | [_DEPRECATED_] (Use `--report-type full`) Shows the full audit report (default `false`) |
| -s | --summary | [_DEPRECATED_] (Use `--report-type summary`) Shows the summary audit report (default `false`) |

@@ -108,0 +111,0 @@ ### (_Optional_) Config file specification

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