Skip to content

Add GitHub security advisory alerts workflow#3087

Merged
wwwillchen merged 1 commit intodyad-sh:mainfrom
wwwillchen-bot:add-security-advisory-alerts-workflow
Mar 27, 2026
Merged

Add GitHub security advisory alerts workflow#3087
wwwillchen merged 1 commit intodyad-sh:mainfrom
wwwillchen-bot:add-security-advisory-alerts-workflow

Conversation

@wwwillchen
Copy link
Copy Markdown
Collaborator

@wwwillchen wwwillchen commented Mar 27, 2026

Summary

  • Adds a nightly GitHub Actions workflow that checks for open security advisories in triage/draft state
  • Sends email alerts via Mailgun when open advisories are found
  • Includes the supporting Node.js script at scripts/github-security-advisory-alert.mjs

Test plan

  • Verify the workflow YAML is valid by triggering a manual workflow_dispatch run
  • Confirm required secrets/vars (KEPPO_GITHUB_APP_ID, KEPPO_GITHUB_APP_PRIVATE_KEY, MAILGUN_API_KEY, MAILGUN_DOMAIN, MAILGUN_FROM_EMAIL, SECURITY_ADVISORY_ALERT_EMAILS) are configured in the ai-bots environment

🤖 Generated with Claude Code


Open with Devin

Adds a nightly workflow that checks for open security advisories in
triage/draft state and sends email alerts via Mailgun.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@wwwillchen
Copy link
Copy Markdown
Collaborator Author

@BugBot run

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

@wwwillchen wwwillchen merged commit b4b8f5e into dyad-sh:main Mar 27, 2026
11 of 13 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds automated monitoring for GitHub Security Advisories so the team is alerted when advisories remain in triage or draft states.

Changes:

  • Introduces a nightly + manual GitHub Actions workflow to check advisory states and trigger alerts.
  • Adds a Node.js script that queries the GitHub API for advisory counts (triage/draft) and sends Mailgun email notifications when non-zero.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
scripts/github-security-advisory-alert.mjs Implements GitHub API pagination/counting and Mailgun email delivery + step summary output.
.github/workflows/github-security-advisory-alerts.yml Schedules and runs the script nightly (and via workflow_dispatch) using a GitHub App token and Mailgun env configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow pins Node.js to v22, but the repo declares engines.node as >=24 and CI initializes Node using node-version-file: package.json. This workflow should follow the same source of truth (or at least use a Node version compatible with the engine constraint) to avoid subtle runtime differences and future breakage when scripts start relying on Node 24+ features.

Suggested change
node-version: 22
node-version-file: package.json

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a script to monitor and alert on GitHub security advisories via Mailgun. The review suggests refactoring the parseRecipients function for better conciseness using modern JavaScript features and recommends dynamically generating report sections based on the ADVISORY_STATES constant to improve maintainability and avoid hardcoded values.

Comment on lines +15 to +35
const parseRecipients = (value) => {
const seen = new Set();
const recipients = [];

for (const entry of value.split(",")) {
const email = entry.trim();
if (!email || seen.has(email)) {
continue;
}
seen.add(email);
recipients.push(email);
}

if (recipients.length === 0) {
throw new Error(
"SECURITY_ADVISORY_ALERT_EMAILS must contain at least one email address",
);
}

return recipients;
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This function can be written more concisely using modern JavaScript features. Using a Set directly from a mapped array simplifies the logic for finding unique, non-empty email addresses, improving readability and maintainability.

const parseRecipients = (value) => {
  const recipients = [
    ...new Set(
      value
        .split(",")
        .map((email) => email.trim())
        .filter(Boolean),
    ),
  ];

  if (recipients.length === 0) {
    throw new Error(
      "SECURITY_ADVISORY_ALERT_EMAILS must contain at least one email address",
    );
  }

  return recipients;
};

Comment on lines +184 to +185
await appendStepSummary(`Triage advisories: ${advisoryCounts.triage}`);
await appendStepSummary(`Draft advisories: ${advisoryCounts.draft}`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The script hardcodes the 'triage' and 'draft' states when generating the summary and email content. This is inconsistent with the data fetching logic, which dynamically uses the ADVISORY_STATES constant. If ADVISORY_STATES is ever updated, the reporting parts of the script will become outdated and require manual changes.

To improve maintainability and robustness, you should generate these report sections dynamically by iterating over ADVISORY_STATES.

For example, for the step summary:

for (const state of ADVISORY_STATES) {
  const capitalizedState = state.charAt(0).toUpperCase() + state.slice(1);
  await appendStepSummary(`${capitalizedState} advisories: ${advisoryCounts[state]}`);
}

A similar approach should be applied to generate the lists and links in the text and HTML email bodies.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@dyad-assistant
Copy link
Copy Markdown
Contributor

🔍 Dyadbot Code Review Summary

Verdict: ✅ YES - Ready to merge

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

Severity File Issue
🟡 MEDIUM scripts/github-security-advisory-alert.mjs:144 Mailgun env vars eagerly validated before advisory count check
🚫 Dropped False Positives (9 items)
  • No pagination loop safety limit — Dropped: Job has a 10-minute timeout; GitHub API won't produce circular Link headers
  • Link header comma-splitting fragility — Dropped: GitHub pagination URLs never contain commas in practice
  • Inconsistent checkout@v5 vs v4 — Dropped: v5 is the latest version, fine to adopt going forward
  • Fetching full advisory payloads just for count — Dropped: Security advisory counts are tiny (typically <10); premature optimization for a nightly script
  • Email lacks responsive/dark mode — Dropped: Simple internal alert email, most clients handle it fine
  • Subject line scannability — Dropped: Current subject is clear and functional
  • Links shown for 0-count advisory states — Dropped: Counts are displayed above the links, providing context
  • Missing lang attribute on HTML email — Dropped: Internal alert email, negligible real-world impact
  • Error messages are developer-facing — Dropped: CI logs are consumed by developers, not end users

Generated by Dyadbot multi-agent code review

Copy link
Copy Markdown
Contributor

@dyad-assistant dyad-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-agent review: 1 issue found

const fromEmail = requireEnv("MAILGUN_FROM_EMAIL");
const recipients = parseRecipients(
requireEnv("SECURITY_ADVISORY_ALERT_EMAILS"),
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM | code-health

Mailgun env vars eagerly validated before advisory count check

All environment variables including MAILGUN_API_KEY, MAILGUN_DOMAIN, MAILGUN_FROM_EMAIL, and SECURITY_ADVISORY_ALERT_EMAILS are validated via requireEnv at the top of main(), before checking whether there are any advisories to report. If totalCount === 0 (the common case for a healthy repo), the script exits without sending email — meaning the Mailgun variables were never needed.

This means a misconfigured or expired Mailgun secret will cause the nightly workflow to fail even when there are zero advisories to report.

💡 Suggestion: Move the Mailgun and recipient env var validation to after the totalCount === 0 early-return, so the workflow only fails on missing email config when it actually needs to send an email.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Confidence score: 3/5

  • There is a concrete medium-risk mismatch in .github/workflows/github-security-advisory-alerts.yml: the workflow uses Node 22 while the repo requires Node >=24, which can cause the advisory alert script (or dependencies) to fail.
  • The issue has relatively high confidence (8/10) and is environment-related, so it is likely reproducible in CI even if application runtime code is unaffected.
  • Pay close attention to .github/workflows/github-security-advisory-alerts.yml - align the workflow runtime to Node 24+ to avoid alert workflow breakage.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/github-security-advisory-alerts.yml">

<violation number="1" location=".github/workflows/github-security-advisory-alerts.yml:42">
P2: The workflow installs Node 22, but the repo’s engines requirement is Node >=24. This can break the alert script or future dependencies that assume 24+. Use Node 24 in the workflow to align with the project’s supported runtime.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The workflow installs Node 22, but the repo’s engines requirement is Node >=24. This can break the alert script or future dependencies that assume 24+. Use Node 24 in the workflow to align with the project’s supported runtime.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/github-security-advisory-alerts.yml, line 42:

<comment>The workflow installs Node 22, but the repo’s engines requirement is Node >=24. This can break the alert script or future dependencies that assume 24+. Use Node 24 in the workflow to align with the project’s supported runtime.</comment>

<file context>
@@ -0,0 +1,55 @@
+      - name: Setup Node
+        uses: actions/setup-node@v4
+        with:
+          node-version: 22
+
+      - name: Send advisory alert email
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants