From c876ddf858930891d0e86d0c7fe847d8fc8061e3 Mon Sep 17 00:00:00 2001 From: Elliot DeNolf Date: Tue, 8 Jul 2025 14:42:24 -0400 Subject: [PATCH] ci: audit-dependencies workflow (#13090) Add weekly check for dependency vulnerabilities. Asana: https://app.asana.com/1/10497086658021/project/1210456585958356/task/1210561338171143 --- .github/workflows/audit-dependencies.sh | 30 ++++++++++++++ .github/workflows/audit-dependencies.yml | 53 ++++++++++++++++++++++-- .gitignore | 2 + 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100755 .github/workflows/audit-dependencies.sh diff --git a/.github/workflows/audit-dependencies.sh b/.github/workflows/audit-dependencies.sh new file mode 100755 index 0000000000..107c2a34a4 --- /dev/null +++ b/.github/workflows/audit-dependencies.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +severity=${1:-"critical"} +audit_json=$(pnpm audit --prod --json) +output_file="audit_output.json" + +echo "Auditing for ${severity} vulnerabilities..." + +echo "${audit_json}" | jq --arg severity "${severity}" ' + .advisories | to_entries | + map(select(.value.patched_versions != "<0.0.0" and .value.severity == $severity) | + { + package: .value.module_name, + vulnerable: .value.vulnerable_versions, + fixed_in: .value.patched_versions + } + ) +' >$output_file + +audit_length=$(jq 'length' $output_file) + +if [[ "${audit_length}" -gt "0" ]]; then + echo "Actionable vulnerabilities found in the following packages:" + jq -r '.[] | "\u001b[1m\(.package)\u001b[0m vulnerable in \u001b[31m\(.vulnerable)\u001b[0m fixed in \u001b[32m\(.fixed_in)\u001b[0m"' $output_file | while read -r line; do echo -e "$line"; done + echo "Output written to ${output_file}" + exit 1 +else + echo "No actionable vulnerabilities" + exit 0 +fi diff --git a/.github/workflows/audit-dependencies.yml b/.github/workflows/audit-dependencies.yml index 026a75ef4f..5eb8349bf7 100644 --- a/.github/workflows/audit-dependencies.yml +++ b/.github/workflows/audit-dependencies.yml @@ -1,11 +1,58 @@ name: audit-dependencies on: + # Sundays at 2am EST + schedule: + - cron: '0 7 * * 0' workflow_dispatch: + inputs: + audit-level: + description: The level of audit to run (low, moderate, high, critical) + required: false + default: critical + debug: + description: Enable debug logging + required: false + default: false + +env: + NODE_VERSION: 23.11.0 + PNPM_VERSION: 9.7.1 + DO_NOT_TRACK: 1 # Disable Turbopack telemetry + NEXT_TELEMETRY_DISABLED: 1 # Disable Next telemetry jobs: - dummy: + audit: runs-on: ubuntu-24.04 steps: - - name: Dummy step - run: echo "This is a dummy step" + - name: Checkout + uses: actions/checkout@v4 + - name: Setup + uses: ./.github/actions/setup + with: + node-version: ${{ env.NODE_VERSION }} + pnpm-version: ${{ env.PNPM_VERSION }} + + - name: Run audit dependencies script + id: audit_dependencies + run: ./.github/workflows/audit-dependencies.sh ${{ inputs.audit-level }} + + - name: Slack notification on failure + if: failure() + uses: slackapi/slack-github-action@v2.1.0 + with: + webhook: ${{ inputs.debug == 'true' && secrets.SLACK_TEST_WEBHOOK_URL || secrets.SLACK_WEBHOOK_URL }} + webhook-type: incoming-webhook + payload: | + { + "username": "GitHub Actions Bot", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "🚨 Actionable vulnerabilities found: " + } + }, + ] + } diff --git a/.gitignore b/.gitignore index 73ca1e3c75..1c37385708 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,8 @@ packages/ui/esbuild packages/next/esbuild packages/richtext-lexical/esbuild +audit_output.json + .turbo # Ignore test directory media folder/files