nuts-foundation / nuts-foundation/nuts-node
Raise PRs for CVE/GHSA fixes detected on release branches instead of proactive Dependabot updates
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 28
- Forks
- 23
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 76
Description
Related: #4508
Problem Statement
V6.2 and V5.4 currently get weekly, patch-only Dependabot PRs for gomod/docker (.github/dependabot.yml:67-133, added in #4508), because Dependabot only reads its config from master and needs target-branch entries to touch other branches at all.
That's more dependency churn than we want on release branches — they should only change when a real CVE or GitHub Security Advisory (GHSA) affects them. Dependabot can't be dialed back to "security-only" on a non-default branch, though: confirmed via GitHub's docs, target-branch excludes an entry from security-update consideration entirely, and security updates always target the default branch regardless of config. Hard platform limitation, not a misconfiguration.
The signal we actually want already exists: govulncheck-cron-schedule.yaml (Go, matrixed over master/V5.4/V6.2) and image-scan-cron-schedule.yaml (Trivy scan of each line's published Docker Hub image), both from #4508, run daily and Slack-alert on a fixable finding — but neither opens a PR; a human still has to act on the alert manually.
Solution
- Remove the proactive
target-branchDependabot entries for V6.2/V5.4. Master's config is unchanged. - Keep the two scheduled scans as detection, unchanged.
- On a fixable finding, have the scan open a PR against the branch with the fix (in addition to the existing Slack alert, which now links the PR).
Auto-merging these (and master's) green PRs is deliberately deferred — see Further Notes.
User Stories
User Stories
- As a maintainer, I want release branches to receive dependency changes only when a real CVE/GHSA affects them, so I'm not reviewing routine bumps against branches meant to stay stable.
- As a maintainer, I want a fixable CVE/GHSA on a release branch to show up as a ready-to-review PR, so I don't have to work out the fix and open the PR by hand after a Slack alert.
Implementation Decisions
Remove proactive Dependabot updates on release branches
Delete the four target-branch: "V6.2"/"V5.4" blocks (docker + gomod) from .github/dependabot.yml:67-133. Non-dependency changes (regular bug fixes) on these branches are unaffected.
Go: govulncheck → PR
On failure for a V5.4/V6.2 matrix entry in govulncheck-cron-schedule.yaml: parse the affected module + minimum fixed version + advisory ID from its output, skip if a PR already exists for that advisory ID on that branch (see guard below), go get <module>@<fixed-version> + go mod tidy on a new branch, push, gh pr create with the advisory ID and target branch in the title/body (e.g. "V6.2: fix GO-2026-XXXX"). Slack links to the PR.
Docker: Trivy → PR
Trivy scans the published image, not the Dockerfile, so the fix is a tag bump on FROM alpine:... / FROM golang:...-alpine in image-scan-cron-schedule.yaml's equivalent PR step. Since the runtime stage already runs apk -U upgrade --no-cache at build time (Dockerfile:26), most Alpine package CVEs are already fixed by any rebuild within the current Alpine line — a finding on a published image mostly means "not rebuilt since the fix landed," not "Dockerfile needs to change." A tag bump matters when the fix needs a newer Alpine/Go-toolchain line; Trivy's output doesn't distinguish these cases outright (open question below).
Merging the PR doesn't publish anything by itself — build-images.yaml only builds/pushes on a push to master or a v* tag (.github/workflows/build-images.yaml:4-9), so the fix reaches Docker Hub only once a maintainer cuts the next patch tag on that branch, same as any other fix. Pinning apk package versions instead (to make the exact fix explicit) isn't an option — already rejected in #4508: Alpine only serves the current version of a package per release line, so a pin breaks the build on the next upstream rotation and defeats apk -U upgrade entirely.
Duplicate-PR guard
Before opening a PR, check for an existing open PR against the same target branch referencing the same advisory ID (in the title) — skip if found. Keyed on (branch, advisory ID) rather than module alone, so two distinct CVEs hitting the same module don't collide, and the same CVE affecting both V5.4 and V6.2 correctly produces one PR per branch rather than being treated as a duplicate.
Modules to build/modify
.github/dependabot.yml: remove the four V5.4/V6.2 entries..github/workflows/govulncheck-cron-schedule.yaml: fix + PR steps..github/workflows/image-scan-cron-schedule.yaml: fix + PR steps.- Script(s) to parse govulncheck/Trivy output and drive the fix.
Testing Decisions
Assert on the resulting commit/PR diff against real fixtures (a go.mod pinned to a known-vulnerable module; a Dockerfile with a known-old tag), not on intermediate parsed data.
Prior art: none directly — closest pattern is Dependabot's own PR shape (single-purpose branch, descriptive title, advisory reference in body).
Impact Assessment
Backwards compatibility: no change to master's cadence. V5.4/V6.2 go from weekly patch bumps to PR-only-on-CVE/GHSA.
Versioning: n/a — tooling/process change.
Configuration/deployment: none.
Security: the two scan jobs move from contents: read to contents: write + pull-requests: write — a compromised scan dependency or parsing-script bug could now push commits/open PRs, not just fail a read-only job.
Out of Scope
- Auto-merge for any of these PRs (master's Dependabot PRs included) — see Further Notes.
- Extending this to
github-actionson release branches — no vulnerability-detection mechanism exists for it today (unlike govulncheck/Trivy for gomod/docker), so this would be new detection infrastructure, not an extension of existing scans. Actions are also a CI/build-time risk rather than a risk in the shipped node/image. Revisit if it becomes a real problem. - Republishing already-tagged Docker Hub images / auto-cutting a new patch release after merge.
Further Notes
Auto-merging green Dependabot/security-fix PRs (including master's) is a real want, but treated as a follow-up optimization on top of this PRD, not a blocker for it: it needs an auto-approve step (branch protection requires 1 review + a signed commit, so green checks alone can't merge) scoped strictly to Dependabot/our-own-automation PRs. Tracked as a separate issue once the items below are in place.
Other open questions:
- Single combined workflow vs. extending the two existing scan workflows independently — leaning toward extending each in place, since their inputs (Go source checkout vs. Docker Hub image) and Slack payloads already differ.
- Whether the Docker fix step needs a "would a plain rebuild already fix this" check before proposing a tag bump, or whether it's simpler to always propose the latest tags and let review catch a no-op.
Implementation Plan
| # | Description | PR | Status | Depends on |
|---|---|---|---|---|
| 1 | Remove proactive target-branch Dependabot entries for V5.4/V6.2 |
#4546 | open | — |
| 2 | Add fix + PR automation to govulncheck-cron-schedule.yaml (Go) |
#4547 | open | — |
| 3 | Add fix + PR automation to image-scan-cron-schedule.yaml (Docker) |
— | — | — |
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing .github/dependabot.yml and the existing govulncheck-cron-schedule.yaml and image-scan-cron-schedule.yaml workflows, along with open PRs #4546 and #4547. The work is done when release-branch Dependabot churn is removed, fixable Go and Docker findings produce guarded branch-targeted PRs, Slack links to them, and fixture-based tests cover the resulting diffs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, github-actions, go
- Domain
- ci-cd, devops, release, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100