Skip to content

Commit

Permalink
New workflow: dependabot-auto-dismiss
Browse files Browse the repository at this point in the history
  • Loading branch information
thypon authored and bcaller committed Dec 21, 2023
1 parent 4cbf2f0 commit 34b30ee
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 0 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/dependabot-auto-dismiss.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Weekly Dependabot Auto Dismiss

on:
schedule:
# Run at 9am UTC every Monday
- cron: "0 0 * * 1"
workflow_dispatch:

jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
with:
node-version: '20.x'
- id: npm
run: cd ${{ github.workspace }}; npm ci
shell: bash
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
SLACK_TOKEN: ${{ secrets.HOTSPOTS_SLACK_TOKEN }}
SLACK_CHANNEL: '#secops-hotspots'
DEBUG: false
with:
github-token: ${{ secrets.DEPENDABOT_AUTO_DISMISS_GITHUB_TOKEN }}
script: |
const debug = process.env.DEBUG === 'true';
const { default: sendSlackMessage } = await import('${{ github.workspace }}/src/sendSlackMessage.js');
const { default: dependabotDismiss } = await import('${{ github.workspace }}/src/dependabotDismiss.js');
const message = await dependabotDismiss({debug, org: process.env.GITHUB_REPOSITORY_OWNER, github: github});
if (message.length > 0)
await sendSlackMessage({debug, username: 'dependabot-auto-dismiss', message: message, channel: process.env.SLACK_CHANNEL, token: process.env.SLACK_TOKEN});
74 changes: 74 additions & 0 deletions src/dependabotDismiss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const Severity = {
low: 0,
medium: 1,
high: 2,
critical: 3,
}

export default async function dependabotDismiss({
org,
minlevel = Severity.low,
debug = false,
hotwords = [' dos ', 'denial of service', 'redos', 'denial-of-service', 'memory explosion'],
githubToken = null,
github = null,
actor = 'security-action',
}) {
let watermark = "The following alerts were dismissed because they contained hotwords:\n\n";
let message = '';

if (!github && githubToken) {
const { Octokit } = await import("octokit");

github = new Octokit({ auth: githubToken })
}

if (!github && !githubToken) {
throw new Error('either githubToken or github is required!');
}

debug = debug === 'true' || debug === true;

if (typeof severity === 'string') {
severity = Severity[severity];
}

const alerts = Array.from(await github.paginate('GET /orgs/{org}/dependabot/alerts', {
org: org,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
},
sort: 'updated',
state: 'open',
severity: Object.keys(Severity).filter(s => Severity[s] >= minlevel)
})).filter(a => hotwords.some(h => a.security_advisory.summary.toLowerCase().includes(h)));

for (const a of alerts) {
// get the first hotword that matches the summary
const hotword = hotwords.find(h => a.security_advisory.summary.toLowerCase().includes(h)).trim();

message += `- [${a.security_advisory.summary} in \`${org}/${a.repository.name}\`](${a.html_url})\n`

if (debug) {
console.log(`Dismissing alert ${a.number} in ${a.repository.name} because it contains the hotword "${hotword}"`);
console.log(`Summary: ${a.security_advisory.summary}`);
continue;
}

await github.request('PATCH /repos/{org}/{repo}/dependabot/alerts/{alert_number}', {
org: org,
repo: a.repository.name,
alert_number: a.number,
dismissed_reason: 'tolerable_risk',
dismissed_comment: `Dismissed by ${actor} because the alert summary contains the hotword "${hotword}"`,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
},
state: 'dismissed',
});
}

if (message.length > 0) {
return watermark + message;
}
}

0 comments on commit 34b30ee

Please sign in to comment.