Skip to content

Add daily security advisory digest to Slack - #21

Merged
ewels merged 3 commits into
mainfrom
security-advisory-digest
Aug 20, 2026
Merged

ewels merged 3 commits into
mainfrom
security-advisory-digest

Conversation

@ewels

@ewels ewels commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds a daily background job (following the existing scheduler/oncall_jobs.py pattern) that polls GitHub's org-wide security-advisories API and posts anything new/changed to the private #security Slack channel.
  • repository_advisory webhooks don't reliably fire for Triage-state reports submitted via GitHub's "Report a vulnerability" form until a maintainer/researcher formally acts on them — that's why nf-core/rnaseq's GHSA-pq68-g636-8gwf sat unnoticed. Polling once a day is enough; only a handful of advisories fire per year.
  • Uses the single GET /orgs/{org}/security-advisories endpoint (one call covers every repo) rather than iterating repos individually, diffing (state, updated_at) against DynamoDB (ADVISORY#{repo} / {ghsa_id} keys, following db/oncall.py's pattern).
  • If the check itself can't run (missing token scope, missing security-manager role, any other API failure), that failure is posted to #security too, not just logged — per feedback that failures should never be silent.
  • Advisory summaries are attacker-influenced (anyone can file a "Report a vulnerability" form against any public nf-core repo), so they're mrkdwn-escaped before being interpolated into the Slack link, mirroring the existing _slack_link escaping in scheduler/oncall_jobs.py.

Setup required before this works

GITHUB_TOKEN's account needs to be added as an org owner or security manager for nf-core (Settings → Access → Security managers), plus either the repository_advisories:write scope (classic PAT) or the "Repository security advisories" permission set to Write (fine-grained PAT). Until that's done, the daily check will post a clear failure notice to #security rather than fail silently.

Test plan

  • pytest — 560 tests pass, including new coverage in tests/test_security_advisories.py (pagination/cursor-following, error propagation, DB round-trips, digest posting, diff/dedupe logic, and mrkdwn-escaping of attacker-controlled advisory text)
  • ruff check / ruff format --check — clean
  • mypy src/ — clean
  • Manual: confirm #security receives the digest once the token has the right org role/scope in production

🤖 Generated with Claude Code

ewels and others added 3 commits August 20, 2026 10:04
repository_advisory webhooks don't reliably fire for Triage-state reports
submitted via GitHub's "Report a vulnerability" form until a maintainer
acts on them, so advisories like nf-core/rnaseq's GHSA-pq68-g636-8gwf can
sit unnoticed. This polls the org-wide security-advisories API once a day,
diffs against DynamoDB state, and posts new/changed advisories to #security.

If the check itself fails (e.g. missing security-manager role or token
scope), that's posted to Slack too rather than only logged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds docs/security-advisories.md (how it works, config, one-time GitHub/Slack
setup) and a short README mention/link. No channel name is called out
explicitly, just "a private Slack channel for the core team".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ewels
ewels merged commit 349e735 into main Aug 20, 2026
3 checks passed
@ewels
ewels deleted the security-advisory-digest branch August 20, 2026 10:02
@ewels ewels mentioned this pull request Aug 20, 2026
3 of 4 tasks
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.

1 participant