diff --git a/.github/workflows/advisory-email-notify.yml b/.github/workflows/advisory-email-notify.yml new file mode 100644 index 0000000..037daf3 --- /dev/null +++ b/.github/workflows/advisory-email-notify.yml @@ -0,0 +1,93 @@ +name: Security Advisory Email Notification + +on: + repository_advisory: + types: [reported, created, published, submitted, reopened] + +permissions: + contents: read + +jobs: + notify-owners: + runs-on: ubuntu-latest + + steps: + - name: Ensure SMTP secrets are configured + id: check_secrets + env: + MAIL_SERVER: ${{ secrets.ADVISORY_MAIL_SERVER }} + MAIL_USERNAME: ${{ secrets.ADVISORY_MAIL_USERNAME }} + MAIL_PASSWORD: ${{ secrets.ADVISORY_MAIL_PASSWORD }} + MAIL_TO: ${{ secrets.ADVISORY_MAIL_TO }} + run: | + missing=() + [ -z "$MAIL_SERVER" ] && missing+=("ADVISORY_MAIL_SERVER") + [ -z "$MAIL_USERNAME" ] && missing+=("ADVISORY_MAIL_USERNAME") + [ -z "$MAIL_PASSWORD" ] && missing+=("ADVISORY_MAIL_PASSWORD") + [ -z "$MAIL_TO" ] && missing+=("ADVISORY_MAIL_TO") + + if [ ${#missing[@]} -gt 0 ]; then + echo "::warning::Missing required secrets: ${missing[*]}. Skipping advisory email notification. Configure these secrets in your repository or organization settings." + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Build email body + if: steps.check_secrets.outputs.skip == 'false' + id: build_body + env: + ADVISORY_TITLE: ${{ github.event.repository_advisory.summary }} + ADVISORY_SEVERITY: ${{ github.event.repository_advisory.severity }} + ADVISORY_STATE: ${{ github.event.repository_advisory.state }} + ADVISORY_CVE: ${{ github.event.repository_advisory.cve_id }} + ADVISORY_URL: ${{ github.event.repository_advisory.html_url }} + ADVISORY_DESCRIPTION: ${{ github.event.repository_advisory.description }} + ADVISORY_ACTION: ${{ github.event.action }} + REPO: ${{ github.repository }} + ACTOR: ${{ github.actor }} + run: | + CVE_LINE="" + if [ -n "$ADVISORY_CVE" ]; then + CVE_LINE="CVE ID : $ADVISORY_CVE"$'\n' + fi + + BODY="A security advisory has been ${ADVISORY_ACTION} on the repository ${REPO}. + +Repository : https://github.com/${REPO} +Action : ${ADVISORY_ACTION} +Title : ${ADVISORY_TITLE} +Severity : ${ADVISORY_SEVERITY} +State : ${ADVISORY_STATE} +${CVE_LINE}Advisory : ${ADVISORY_URL} +Reported by: ${ACTOR} + +--- Description --- +${ADVISORY_DESCRIPTION} + +--- +This notification was sent automatically by GitHub Actions. +Repository: https://github.com/${REPO} +" + + # Write to file to avoid multiline env issues + printf '%s' "$BODY" > /tmp/advisory_body.txt + echo "body_file=/tmp/advisory_body.txt" >> "$GITHUB_OUTPUT" + + - name: Send email to org owners + if: steps.check_secrets.outputs.skip == 'false' + # dawidd6/action-send-mail v3.12.0 — pinned to exact commit for supply-chain security. + # Verify: https://github.com/dawidd6/action-send-mail/commit/2cea9617b09d83a84e7015b8b4c893f01b028020 + uses: dawidd6/action-send-mail@2cea9617b09d83a84e7015b8b4c893f01b028020 + with: + server_address: ${{ secrets.ADVISORY_MAIL_SERVER }} + # ADVISORY_MAIL_PORT defaults to 465 (SMTPS / implicit TLS). + # Set the secret to 587 and secure to false if your SMTP server requires STARTTLS instead. + server_port: ${{ secrets.ADVISORY_MAIL_PORT || 465 }} + secure: ${{ secrets.ADVISORY_MAIL_SECURE || true }} + username: ${{ secrets.ADVISORY_MAIL_USERNAME }} + password: ${{ secrets.ADVISORY_MAIL_PASSWORD }} + subject: "[Security Advisory] [${{ github.event.repository_advisory.severity }}] ${{ github.event.repository_advisory.summary }} — ${{ github.repository }}" + to: ${{ secrets.ADVISORY_MAIL_TO }} + from: "GitHub Advisory Bot <${{ secrets.ADVISORY_MAIL_USERNAME }}>" + body: file:///tmp/advisory_body.txt