init project

This commit is contained in:
Celogeek 2022-05-11 12:15:49 +02:00
parent 3fd7e846e7
commit f1039c8c92
Signed by: celogeek
GPG Key ID: E6B7BDCFC446233A
5 changed files with 151 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

View File

@ -1,2 +1,9 @@
# yarn-audit-sonar
Convert yarn audit into a Sonar compatible format
## Usage
```
yarn audit --group dependencies --json | npx yarn-audit-sonar > yarn-sonar.json
```

110
index.js Normal file
View File

@ -0,0 +1,110 @@
const fs = require('fs');
const split = require('split');
if (!fs.existsSync('yarn.lock')) {
console.error('yarn.lock is missing');
process.exit(1);
}
function parseYarnLock() {
let pos = 0;
let currentModule = '';
const yarnLock = {};
for (const row of fs.readFileSync('yarn.lock', 'utf8').split('\n')) {
pos++;
if (row.length > 0 && row[0] != ' ') {
currentModule = row.replace(/"/g, '').replace(/(..*?)@.*/, '$1');
}
if (new RegExp(' +version').test(row)) {
const version = row.replace(/\s+version "(.*)"/, '$1');
if (!yarnLock[currentModule]) yarnLock[currentModule] = {};
yarnLock[currentModule][version] = {
'startLine': pos,
'endLine': pos,
'startColumn': 1,
'endColumn': row.length,
};
}
}
return yarnLock;
}
function yarnLockRange(yarnLock, moduleName, version) {
if (yarnLock[moduleName] && yarnLock[moduleName][version]) {
return yarnLock[moduleName][version];
} else {
return {
'startLine': 1,
};
}
}
const yarnLock = parseYarnLock();
const severities = {
info: 'INFO',
low: 'MINOR',
moderate: 'MINOR',
high: 'CRITICAL',
critical: 'BLOCKER',
};
const resolvedIds = new Set();
const stats = {};
let firstLine = true;
function processRow(row) {
if (!row) return;
const {type, data} = JSON.parse(row);
if (type !== 'auditAdvisory') return;
const {advisory, resolution} = data;
if (resolvedIds.has(resolution.id)) return;
const [mainVersion, ...otherVersions] = new Set(advisory.findings.map((f) => f.version));
if (!firstLine) {
process.stdout.write(',');
} else {
firstLine = false;
}
process.stdout.write(JSON.stringify({
engineId: 'yarn-audit',
ruleId: resolution.id.toString(),
severity: severities[advisory.severity] || 'INFO',
type: 'VULNERABILITY',
efforMinutes: 0,
primaryLocation: {
'message': advisory.overview,
'filePath': 'yarn.lock',
'textRange': yarnLockRange(yarnLock, advisory.module_name, mainVersion),
},
secondaryLocations: otherVersions.map((version) => {
return {
'message': advisory.overview,
'filePath': 'yarn.lock',
'textRange': yarnLockRange(yarnLock, advisory.module_name, version),
};
}),
}));
stats[advisory.severity] = (stats[advisory.severity] || 0) + 1;
}
process.stdout.write('{"issues":[');
process
.stdin
.pipe(split())
.on('data', processRow)
.on('end', () => {
process.stdout.write(']}\n');
const out = [];
let total = 0;
for(const [k,v] of Object.entries(stats)) {
out.push(`${v} ${k}`);
total += v;
}
console.error('yarn audit:');
console.error(` ${total} vulnerabilities found`);
if (total > 0) {
console.error(` Severity: ${out.join(' | ')}`);
}
});

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "yarn-audit-sonar",
"version": "1.0.0",
"description": "Convert YARN audit to Sonar compatible format",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://git.celogeek.com/celogeek/yarn-audit-sonar.git"
},
"author": "Celogeek",
"license": "ISC",
"dependencies": {
"split": "^1.0.1"
}
}

15
yarn.lock Normal file
View File

@ -0,0 +1,15 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
split@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
dependencies:
through "2"
through@2:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=