[FP]: pkg:nuget/[email protected] #4711
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: False Positive Approvals | |
on: | |
issue_comment: | |
types: [ created ] | |
permissions: {} | |
jobs: | |
update_suppression: | |
permissions: | |
contents: write # to push changes in repo (jamesives/github-pages-deploy-action) | |
issues: write | |
name: Update Suppression Rules | |
if: ${{ !github.event.issue.pull_request && | |
contains(github.event.issue.labels.*.name, 'FP Report') && | |
contains(github.event.comment.body,'approved') && | |
(github.event.comment.user.login == 'jeremylong' || | |
github.event.comment.user.login == 'aikebah' || | |
github.event.comment.user.login == 'nhumblot') }} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
ref: generatedSuppressions | |
- uses: actions/[email protected] | |
- run: | | |
npm install [email protected] | |
npm install fs | |
- name: Commit Suppression Rule | |
id: fp-ops-commit | |
uses: actions/[email protected] | |
with: | |
script: | | |
const { execSync } = require("child_process"); | |
const { XMLParser } = require("fast-xml-parser"); | |
const fs = require('fs'); | |
console.log('evaluating issue #' + context.issue.number); | |
const { data: comments } = await github.rest.issues.listComments({ | |
issue_number: context.issue.number, | |
owner: context.issue.owner, | |
repo: context.issue.repo, | |
}) | |
console.log('author0: ' + comments[0].user.login); | |
console.log('comments0: ' + comments[0].body); | |
let botComments = comments.filter(comment => | |
comment.user.login === 'github-actions[bot]' && | |
comment.body.includes('<suppress base="true">') && | |
comment.body.includes('Suppression rule:') | |
) | |
console.log('bot comments: ' + botComments); | |
if (botComments.length<=0) { | |
console.log('Suppression rule from github-actions not found'); | |
core.setOutput('publish', 'false'); | |
//using core.setFailed() ended execution and the check for failure below (to post a message did not work) | |
core.setOutput('failed', 'true'); | |
return; | |
} | |
let lastComment = botComments[botComments.length-1]; | |
let data = lastComment.body.split('```'); | |
let suppression = data[data.length-2].substring(3).trim(); | |
console.log("suppression rule: " + suppression); | |
const options = { | |
ignoreAttributes : true | |
}; | |
const parser = new XMLParser(options); | |
let proposedRule = parser.parse(suppression); | |
let commitComment = proposedRule.suppress.notes.trim(); | |
commitComment = commitComment.replace(/[[\]{}`'";|\/\\]/g, ''); | |
console.log("commit comment: " + commitComment); | |
//validate we haven't already suppressed this one. | |
const generatedSuppressions = fs.readFileSync('generatedSuppressions.xml', 'utf8'); | |
let found = false; | |
let previousReportNotes = ''; | |
if (!(generatedSuppressions && generatedSuppressions.trim() === '')) { | |
let rules = parser.parse(generatedSuppressions); | |
for (r of rules.suppress) { | |
if (proposedRule.suppress.packageUrl === r.packageUrl && | |
proposedRule.suppress.cpe === r.cpe) { | |
found = true; | |
previousReportNotes = r.notes.trim(); | |
break; | |
} | |
} | |
} | |
if (found) { | |
let prevIssue = previousReportNotes.split('#')[1].trim(); | |
github.rest.issues.createComment({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: 'Suppress already exists in `generatedSuppressions` branch. See issue #' + prevIssue + '.', | |
}); | |
github.rest.issues.addLabels({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
labels: ['duplicate'] | |
}); | |
github.rest.issues.update({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
state: 'closed', | |
}); | |
core.setOutput('publish', 'false'); | |
} else { | |
fs.appendFileSync('generatedSuppressions.xml', '\n' + suppression.trim(), function (err) { | |
if (err) throw err; | |
console.log('Suppression rule added'); | |
}); | |
if (!fs.existsSync('./suppressions')){ | |
fs.mkdirSync('./suppressions'); | |
} | |
fs.appendFileSync('suppressions/publishedSuppressions.xml', '<?xml version="1.0" encoding="UTF-8"?>\n<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">' + generatedSuppressions + '\n' + suppression.trim() + '\n</suppressions>', function (err) { | |
if (err) throw err; | |
console.log('publishedSuppressions.xml created'); | |
}); | |
fs.appendFileSync('.git/config', ` | |
[user] | |
name = github-actions[bot] | |
email = 41898282+github-actions[bot]@users.noreply.github.com | |
`, err => { | |
if (err) throw err; | |
}); | |
execSync('git commit -m "fix(fp): ' + commitComment + '" generatedSuppressions.xml;git push origin generatedSuppressions', (err, stdout, stderr) => { | |
if (err) throw err; | |
console.log('committed suppression rule'); | |
}); | |
github.rest.issues.createComment({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: 'Suppress rule has been added to the `generatedSuppressions` branch.', | |
}); | |
github.rest.issues.update({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
state: 'closed', | |
}); | |
core.setOutput('publish', 'true'); | |
} | |
- name: Publish Updated Suppressions | |
if: ${{ steps.fp-ops-commit.outputs.publish == 'true' }} | |
uses: JamesIves/[email protected] | |
with: | |
branch: gh-pages | |
folder: suppressions | |
target-folder: suppressions | |
- name: Message failure | |
if: ${{ failure() || steps.fp-ops-commit.outputs.failed }} | |
uses: actions/[email protected] | |
with: | |
script: | | |
github.rest.issues.createComment({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: 'Failed to automatically generate and publish the suppression rule!\n\n' + 'Link to action run: ' + context.serverUrl + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, | |
}); |