npm-audit-sarif
Version:
A tool for converting npm-audit json output to sarif format
150 lines (126 loc) • 3.94 kB
text/typescript
const fs = require('fs')
const {
SarifBuilder,
SarifRunBuilder,
SarifResultBuilder,
} = require('node-sarif-builder')
const yargs = require('yargs')
export function minVal(val: number) {
if (val) {
return val;
}
return 1;
}
export function relative(rootdir: string, fullpath: string) {
if (rootdir) {
if (fullpath.toLowerCase().startsWith(rootdir.toLowerCase())) {
return fullpath.substring(rootdir.length);
}
}
return fullpath;
}
export function main() {
const argv = yargs
.option('o', {
alias: 'output',
describe: 'Output filename',
type: 'string',
demandOption: false,
})
.option('r', {
alias: 'root',
describe: 'Root directory',
type: 'string',
demandOption: false,
})
.demandCommand(1)
.usage('Usage: $0 [options] <filename>').argv;
exportSarif(argv._[0], argv.output, argv.root);
}
export interface Via
{
source: number;
name: string;
dependency: string;
title: string;
url: string;
severity: string;
cwe: string[];
range: string;
};
export interface Vulnerability
{
name: string;
severity: string;
via: Via[] | string[];
isDirect: boolean;
range: string;
fixAvailable: boolean;
};
export function exportSarif(filename:string, outputfilename:string,rootdir:string) {
const results = JSON.parse(fs.readFileSync(filename, 'utf8'))
// SARIF builder
const sarifBuilder = new SarifBuilder()
// SARIF Run builder
const sarifRunBuilder = new SarifRunBuilder().initSimple({
toolDriverName: 'npm-audit-sarif',
toolDriverVersion: '0.0.13',
})
for (const key in results.vulnerabilities) {
const value = results.vulnerabilities[key];
for (const viaobj of value.via){
if (typeof (viaobj) == "string") {
continue;
}
const via: Via = viaobj as Via;
let msg = via.severity.toUpperCase() + " - package: " + via.name + " failed audit: " + via.title + " in versions: " + via.range + " - " + via.url;
if (via.cwe.length) {
msg += " - [";
let first = true;
for (const cwe of via.cwe) {
if (!first) {
msg += ",";
}
msg += cwe;
first = false;
}
msg += "]";
}
let level = "error";
if (via.severity == "moderate") {
level = "info";
}
if (via.severity == "high") {
level = "warning";
}
if (via.severity == "critical") {
level = "error";
}
const ruleId = "npm-audit-" + key.toLowerCase().replaceAll("_", "-").replaceAll(" ", "-");
const sarifResultBuilder = new SarifResultBuilder()
const sarifResultInit = {
ruleId: ruleId,
level: level,
messageText: msg,
fileUri: relative(rootdir, "package.json"),
startLine: 0,
startColumn: 0,
endLine: 0,
endColumn: 0
}
sarifResultInit.startLine = 1;
sarifResultInit.startColumn = 1;
sarifResultInit.endLine = 1;
sarifResultInit.endColumn = 1;
sarifResultBuilder.initSimple(sarifResultInit)
sarifRunBuilder.addResult(sarifResultBuilder)
}
}
sarifBuilder.addRun(sarifRunBuilder)
const json = sarifBuilder.buildSarifJsonString({ indent: true })
if (outputfilename) {
fs.writeFileSync(outputfilename, json)
} else {
console.log(json)
}
}