From cdf0a8f7d709ea6e60290d2b0f0cf2aac9e7d639 Mon Sep 17 00:00:00 2001 From: Tobias Wochinger Date: Fri, 24 Apr 2020 12:15:26 +0200 Subject: [PATCH 1/5] check if issue with this content already exists --- src/index.ts | 4 ++-- src/issue.ts | 43 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index ed6dfaa..c5551f0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import * as core from '@actions/core'; import { Trivy, Downloader } from './trivy'; -import { createIssue } from './issue'; +import { getExistingOrCreateIssue } from './issue'; import { TrivyOption, IssueOption, @@ -69,7 +69,7 @@ async function run() { .split(','), }; const token: string = core.getInput('token', { required: true }); - const output: IssueResponse = await createIssue(token, issueOption); + const output: IssueResponse = await getExistingOrCreateIssue(token, issueOption); core.setOutput('html_url', output.htmlUrl); core.setOutput('issue_number', output.issueNumber.toString()); } catch (error) { diff --git a/src/issue.ts b/src/issue.ts index 1d38f1e..a91e3e9 100644 --- a/src/issue.ts +++ b/src/issue.ts @@ -1,11 +1,26 @@ import { Octokit } from '@octokit/rest'; +import * as core from '@actions/core'; import * as github from '@actions/github'; import { IssueOption, IssueResponse } from './interface'; -export async function createIssue( +async function get_trivy_issues(repository: string, token: string) { + const client: Octokit = new Octokit({ auth: token }); + + let trivyIssues = await client.issues.list( + { state: "open", labels: "tool:trivy" , filter: "all" }) + + trivyIssues = trivyIssues.data.filter(issue => issue.repository.full_name == repository) + + core.info(`Found ${trivyIssues.length} open trivy issues for this repository.`) + core.exportVariable('issues', trivyIssues); + + return trivyIssues +} + +async function createIssue( token: string, options: IssueOption -): Promise { +): Promise { const client: Octokit = new Octokit({ auth: token }); const { data: issue, @@ -15,9 +30,33 @@ export async function createIssue( ...options, } ); + return issue +} + +export async function getExistingOrCreateIssue( + token: string, + options: IssueOption +): Promise { + const currentVulnerability = options.body.match(/\|CVE-[0-9-]+\|/) + core.info(`Current vulnerability is ${currentVulnerability}`) + core.exportVariable('v', currentVulnerability); + + let issue = null + if (currentVulnerability != null) { + const trivyIssues = await get_trivy_issues(github.context.repo, token) + issue = trivyIssues.find(issue => issue.body.includes(currentVulnerability[0])) + } + + if (issue != null) { + core.info("Found existing issue. Skip creating a new one.") + } else { + issue = await createIssue(token, options) + } + const result: IssueResponse = { issueNumber: issue.number, htmlUrl: issue.html_url, }; + return result; } From ad34351a3f5c6d6be062048c6af0bcade633289f Mon Sep 17 00:00:00 2001 From: Tobias Wochinger Date: Tue, 28 Apr 2020 10:50:05 +0200 Subject: [PATCH 2/5] add option to fail if vulnerability was found --- README.md | 1 + action.yml | 4 ++++ dist/index.js | 3 +++ src/index.ts | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/README.md b/README.md index 6bb2647..e082ff0 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ If vulnerabilities are found by Trivy, it creates the following GitHub Issue. |issue_title|False|Security Alert|Issue title| |issue_label|False|trivy,vulnerability|Issue label (separated by commma)| |issue_assignee|False|N/A|Issue assignee (separated by commma)| +|fail_on_vulnerabilities|False|false|Whether the action should fail if any vulnerabilities were found.| ### Outputs diff --git a/action.yml b/action.yml index a702767..50904bc 100644 --- a/action.yml +++ b/action.yml @@ -39,6 +39,10 @@ inputs: issue_assignee: description: 'Issue assignee (separated by commma)' required: false + fail_on_vulnerabilities: + description: Whether the action should fail if a vulnerability was found + default: 'false' + required: false outputs: issue_number: diff --git a/dist/index.js b/dist/index.js index 329287c..bb16b23 100644 --- a/dist/index.js +++ b/dist/index.js @@ -6593,6 +6593,9 @@ function run() { const output = yield issue_1.createOrUpdateIssue(token, image, issueOption); core.setOutput('html_url', output.htmlUrl); core.setOutput('issue_number', output.issueNumber.toString()); + if (core.getInput("fail_on_vulnerabilities") === 'true') { + core.setFailed(`Vulnerabilities found.\n${issueContent}`); + } } catch (error) { core.error(error.stack); diff --git a/src/index.ts b/src/index.ts index 9ebd9ff..c8cfcd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -72,6 +72,10 @@ async function run() { const output: IssueResponse = await createOrUpdateIssue(token, image, issueOption); core.setOutput('html_url', output.htmlUrl); core.setOutput('issue_number', output.issueNumber.toString()); + + if (core.getInput("fail_on_vulnerabilities") === 'true') { + core.setFailed(`Vulnerabilities found.\n${issueContent}`) + } } catch (error) { core.error(error.stack); core.setFailed(error.message); From 42bdc19fa6f86d81bd388b0aef41ea987190b4c3 Mon Sep 17 00:00:00 2001 From: m-vdb Date: Fri, 16 Apr 2021 16:14:48 +0200 Subject: [PATCH 3/5] fix version matching in tests --- __tests__/trivy.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__tests__/trivy.test.ts b/__tests__/trivy.test.ts index 4fa60c9..77416ff 100644 --- a/__tests__/trivy.test.ts +++ b/__tests__/trivy.test.ts @@ -36,7 +36,7 @@ describe('getDownloadUrl', () => { const os = 'Linux'; const result = await downloader['getDownloadUrl'](version, os); expect(result).toMatch( - /releases\/download\/v[0-9]\.[0-9]\.[0-9]\/trivy_[0-9]\.[0-9]\.[0-9]_Linux-64bit\.tar\.gz$/ + /releases\/download\/v[0-9]+\.[0-9]+\.[0-9]+\/trivy_[0-9]+\.[0-9]+\.[0-9]+_Linux-64bit\.tar\.gz$/ ); }); From 33e69986545936db223d5288849bc76202671709 Mon Sep 17 00:00:00 2001 From: m-vdb Date: Fri, 16 Apr 2021 16:22:24 +0200 Subject: [PATCH 4/5] issue body should contain image name --- __tests__/trivy.test.ts | 7 +++++-- src/index.ts | 2 +- src/trivy.ts | 5 +++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/__tests__/trivy.test.ts b/__tests__/trivy.test.ts index 77416ff..56af097 100644 --- a/__tests__/trivy.test.ts +++ b/__tests__/trivy.test.ts @@ -198,6 +198,8 @@ describe('Trivy scan', () => { }); describe('Parse', () => { + const image: string = 'alpine:3.10'; + test('the result without vulnerabilities', () => { const vulnerabilities: Vulnerability[] = [ { @@ -205,7 +207,7 @@ describe('Parse', () => { Vulnerabilities: null, }, ]; - const result = trivy.parse(vulnerabilities); + const result = trivy.parse(image, vulnerabilities); expect(result).toBe(''); }); @@ -248,10 +250,11 @@ describe('Parse', () => { ], }, ]; - const result = trivy.parse(vulnerabilities); + const result = trivy.parse(image, vulnerabilities); expect(result).toMatch( /\|Title\|Severity\|CVE\|Package Name\|Installed Version\|Fixed Version\|References\|/ ); + expect(result).toContain(image); }); }); diff --git a/src/index.ts b/src/index.ts index c8cfcd4..ad46d9a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -47,7 +47,7 @@ async function run() { return; } - const issueContent: string = trivy.parse(result as Vulnerability[]); + const issueContent: string = trivy.parse(image, result as Vulnerability[]); if (issueContent === '') { core.info( diff --git a/src/trivy.ts b/src/trivy.ts index 61fee50..4514c62 100644 --- a/src/trivy.ts +++ b/src/trivy.ts @@ -164,7 +164,7 @@ export class Trivy { `); } - public parse(vulnerabilities: Vulnerability[]): string { + public parse(image: string, vulnerabilities: Vulnerability[]): string { let issueContent: string = ''; for (const vuln of vulnerabilities) { @@ -191,7 +191,8 @@ export class Trivy { } issueContent += `${vulnTable}\n\n`; } - return issueContent; + + return issueContent ? `_(image scanned: \`${image}\`)_\n\n${issueContent}` : issueContent; } private validateOption(option: TrivyOption): void { From d9d33fbbe2e46f3f8164c8a00c40b5bd224be624 Mon Sep 17 00:00:00 2001 From: m-vdb Date: Fri, 16 Apr 2021 16:22:52 +0200 Subject: [PATCH 5/5] bump build --- dist/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/index.js b/dist/index.js index bb16b23..d56c8d6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -6572,7 +6572,7 @@ function run() { ${result}`); return; } - const issueContent = trivy.parse(result); + const issueContent = trivy.parse(image, result); if (issueContent === '') { core.info('Vulnerabilities were not found.\nYour maintenance looks good 👍'); return; @@ -13337,7 +13337,7 @@ class Trivy { error: ${result.error} `); } - parse(vulnerabilities) { + parse(image, vulnerabilities) { let issueContent = ''; for (const vuln of vulnerabilities) { if (vuln.Vulnerabilities === null) @@ -13361,7 +13361,7 @@ class Trivy { } issueContent += `${vulnTable}\n\n`; } - return issueContent; + return issueContent ? `_(image scanned: \`${image}\`)_\n\n${issueContent}` : issueContent; } validateOption(option) { this.validateSeverity(option.severity.split(','));