Skip to content

Commit eb0b184

Browse files
committed
Parse the result from Retire.js and present it as Azure DevOps warnings
1 parent c3031ec commit eb0b184

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

tasks/retire/index.js

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ async function run() {
88
const failOnVulnerabilities = tl.getBoolInput('failOnVulnerabilities', false);
99

1010
// Construct the retire command
11-
let command = 'retire --colors';
11+
let command = 'retire --outputformat json';
1212

1313
if (verbose) {
1414
command += ' --verbose';
@@ -24,16 +24,70 @@ async function run() {
2424

2525
// Install Retire.js
2626
tl.debug('Installing Retire.js...');
27-
await tl.exec('npm', ['install', '-g', 'retire']);
27+
await tl.exec('npm', ['install', '-g', 'retire'], {silent: true});
2828

29-
// Run Retire.js
29+
// Run Retire.js and capture output
3030
tl.debug(`Executing command: ${command}`);
31-
await tl.exec('sh', ['-c', command]); // Use 'sh -c' for cross-platform compatibility
31+
const result = tl.execSync('sh', ['-c', command], {silent: true});
3232

33-
tl.setResult(tl.TaskResult.Succeeded, 'Retire completed successfully');
33+
const stdout = result.stdout?.toString() || '';
34+
let hasRealVulnerabilities = false;
35+
36+
if (stdout.trim().startsWith('{')) {
37+
try {
38+
const parsed = JSON.parse(stdout);
39+
const matches = parsed.data || [];
40+
41+
for (const entry of matches) {
42+
const file = entry.file;
43+
const results = Array.isArray(entry.results) ? entry.results : [];
44+
45+
for (const vuln of results) {
46+
const vulnerabilities = Array.isArray(vuln.vulnerabilities) ? vuln.vulnerabilities : [];
47+
const hasVulns = vulnerabilities.length > 0;
48+
49+
const component = vuln.component || 'unknown';
50+
const version = vuln.version || 'unknown';
51+
const identifiers = vuln.identifiers || {};
52+
const cves = identifiers.CVE?.join(', ') || 'None';
53+
const infoLinks = hasVulns
54+
? vulnerabilities.flatMap(v => v.info || []).join(', ') || 'None'
55+
: 'None';
56+
const severity = (vulnerabilities.length > 0 && vulnerabilities[0].severity)
57+
? vulnerabilities[0].severity
58+
: 'none';
59+
60+
const message =
61+
`- Component: ${component}
62+
- Version: ${version}
63+
- File: ${file}
64+
- Severity: ${severity}
65+
- CVEs: ${cves}
66+
- Info: ${infoLinks}`;
67+
68+
if (hasVulns) {
69+
hasRealVulnerabilities = true;
70+
tl.warning(`Vulnerable library found:\n${message}`);
71+
} else if (verbose) {
72+
console.log(`Library matched but no known vulnerabilities:\n${message}`);
73+
}
74+
}
75+
}
76+
} catch (err) {
77+
tl.warning('Could not parse JSON output from Retire.js');
78+
}
79+
} else {
80+
tl.warning('No JSON output detected from Retire.js');
81+
}
82+
83+
if (hasRealVulnerabilities && failOnVulnerabilities) {
84+
tl.setResult(tl.TaskResult.Failed, 'Vulnerabilities were found and failOnVulnerabilities is true.');
85+
} else {
86+
tl.setResult(tl.TaskResult.Succeeded, 'Retire completed successfully');
87+
}
3488
} catch (err) {
3589
tl.setResult(tl.TaskResult.Failed, `Task failed: ${err.message}`);
3690
}
3791
}
3892

39-
run();
93+
run();

tasks/retire/task.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
"author": "elmah.io",
1313
"version": {
1414
"Major": 1,
15-
"Minor": 0,
16-
"Patch": 8
15+
"Minor": 1,
16+
"Patch": 20
1717
},
1818
"inputs": [
1919
{

vss-extension.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"id": "retire-extension",
44
"name": "Retire.js",
55
"publisher": "elmahio",
6-
"version": "1.0.8",
6+
"version": "1.1.20",
77
"tags": [
88
"javascript",
99
"security",

0 commit comments

Comments
 (0)