Security Vulnerability Slack Notification #108
This file contains hidden or 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: Security Vulnerability Slack Notification | |
| on: | |
| schedule: | |
| # Runs every hour at minute 0 | |
| - cron: '0 * * * *' | |
| # Allows you to test manually | |
| workflow_dispatch: | |
| jobs: | |
| check-alerts: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v3 | |
| - name: Check for New Alerts | |
| env: | |
| GH_TOKEN: ${{ secrets.DEPENDABOT_PAT }} | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| run: | | |
| # 1. Calculate time 65 minutes ago | |
| # This ensures we only notify about alerts created since the last run | |
| TIME_THRESHOLD=$(date -u -d '65 minutes ago' +'%Y-%m-%dT%H:%M:%SZ') | |
| echo "Checking for alerts created after: $TIME_THRESHOLD" | |
| # 2. Fetch Open Alerts | |
| RAW_DATA=$(gh api "/repos/${{ github.repository }}/dependabot/alerts?state=open") | |
| # 3. Filter for NEW items only | |
| # We look for Open alerts created > 65 mins ago | |
| ALERTS=$(echo "$RAW_DATA" | jq --arg TIME "$TIME_THRESHOLD" \ | |
| '[ .[] | select(.state == "open") | select(.created_at > $TIME) ]') | |
| # --- FOR TESTING ONLY: UNCOMMENT BELOW TO IGNORE TIME FILTER --- | |
| # ALERTS=$(echo "$RAW_DATA" | jq '[ .[] | select(.state == "open") ]') | |
| # --------------------------------------------------------------- | |
| # 4. Check count | |
| LENGTH=$(echo "$ALERTS" | jq 'length') | |
| if [ "$LENGTH" -eq 0 ]; then | |
| echo "::notice:: No new alerts found in the last hour." | |
| exit 0 | |
| fi | |
| echo "Found $LENGTH new alert(s). Sending notifications..." | |
| REPO_NAME="${{ github.repository }}" | |
| ISSUE_USER="Dependabot" | |
| # 5. LOOP through each alert | |
| echo "$ALERTS" | jq -c '.[]' | while read -r alert; do | |
| # Extract details | |
| SUMMARY=$(echo "$alert" | jq -r '.security_advisory.summary // "Security Vulnerability"') | |
| PACKAGE=$(echo "$alert" | jq -r '.dependency.package.name // "Unknown Package"') | |
| SEVERITY=$(echo "$alert" | jq -r '.security_advisory.severity // "Unknown"') | |
| ISSUE_URL=$(echo "$alert" | jq -r '.html_url // .url // "https://github.com"') | |
| # Format Title (e.g., "Cross-site Scripting - next (high)") | |
| ISSUE_TITLE="${SUMMARY} - ${PACKAGE} (${SEVERITY})" | |
| echo "Sending alert for: $PACKAGE" | |
| # Build Slack Message | |
| MESSAGE_TEXT=$(jq -n \ | |
| --arg repo "$REPO_NAME" \ | |
| --arg title "$ISSUE_TITLE" \ | |
| --arg user "$ISSUE_USER" \ | |
| --arg url "$ISSUE_URL" \ | |
| --arg template "*🚨 New Dependabot Alert ($REPO_NAME) 🚨*\n\n*Issue Title:* $ISSUE_TITLE\n*Opened By:* $ISSUE_USER\n\n*View Issue:* $ISSUE_URL" \ | |
| '$template') | |
| # Build Payload | |
| SLACK_PAYLOAD=$(jq -n \ | |
| --arg text "$MESSAGE_TEXT" \ | |
| '{ | |
| "channel": "#docs-devdocs-notifications", | |
| "username": "Security Vulnerability Slack Notification", | |
| "icon_emoji": ":rotating_light:", | |
| "text": $text | |
| }') | |
| # Send to Slack | |
| curl -s -X POST \ | |
| -H 'Content-type: application/json' \ | |
| --data "$SLACK_PAYLOAD" \ | |
| "$SLACK_WEBHOOK_URL" | |
| sleep 1 | |
| done |