You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
.github/workflows/ci.yml runs gofmt -l, go build ./..., go vet ./... and go test -race ./.... That is a good gate for correctness and it catches nothing about dependencies.
go.mod pulls in the WebRTC stack (pion/webrtc/v4, pion/ice/v4, pion/turn/v5, pion/rtp, pion/interceptor), a Postgres driver, a JWT library, a WebSocket library, and four provider SDKs. Every one of those parses input from the network, and two of them — the ICE/DTLS path and golang-jwt — parse input from unauthenticated strangers. Nothing tells the repo when one of them ships a CVE.
The Docker image has the same hole and a wider one: the runtime stage is node:22-bookworm-slim, it installs tsx globally, creates a Python venv, and runs npm install across every plugin directory. That is three ecosystems of transitive dependencies in the published image, and nothing scans it.
For a project asking people to run it as infrastructure, each of these is a one-file addition, and their absence is more conspicuous than any single one of them.
Proposed change
Four separate, independently mergeable pieces. golangci-lint is deliberately excluded here because #27 already covers it.
1. govulncheck in CI.golang/govulncheck-action, on PRs and pushes to main. It reports only vulnerabilities in code paths actually reachable from this module, so the false-positive rate is low enough to gate on rather than merely report.
2. Dependabot..github/dependabot.yml with four ecosystems: gomod (root), github-actions, npm (the plugins/ directories), and pip (the Python plugin venv built in the Dockerfile). Group patch and minor updates into one weekly PR per ecosystem — ungrouped Dependabot on a repo with this many dependencies produces enough noise to get muted, which is the same as not having it.
Pin the Pion packages to a separate group and do not auto-merge them. A minor bump in the media stack is a real behavioural change on a latency-sensitive path, and CI cannot tell you whether audio still sounds right.
3. Image scanning. Trivy or Grype against the built image in the release/publish workflow, failing on HIGH and CRITICAL with a documented allowlist file for anything that is genuinely unfixable in node:22-bookworm-slim. Upload SARIF so findings land in the Security tab instead of only in a log.
4. SBOM.syft or anchore/sbom-action attaching a CycloneDX SBOM to each release. Cheap, and it is the first thing anyone doing vendor review asks for.
Worth doing at the same time, since it is the same category: a SECURITY.md supported-versions table (the file exists but predates any release), and enabling GitHub's secret scanning and push protection on the repo.
Acceptance criteria
govulncheck runs on every PR and fails the build on a reachable vulnerability.
.github/dependabot.yml covers gomod, github-actions, npm, pip, with grouped updates and Pion held separate.
Image scan runs on publish, fails on HIGH/CRITICAL, uploads SARIF.
Allowlist file exists with a comment explaining each entry.
SBOM attached to releases.
README badge for the security workflow, next to the CI badge.
Pointers
.github/workflows/ci.yml — where govulncheck slots in as a step or a parallel job
go.mod — the dependency set being covered
Dockerfile — runtime stage L16 onward, the npm/pip installs that scanning targets
Problem
.github/workflows/ci.ymlrunsgofmt -l,go build ./...,go vet ./...andgo test -race ./.... That is a good gate for correctness and it catches nothing about dependencies.go.modpulls in the WebRTC stack (pion/webrtc/v4,pion/ice/v4,pion/turn/v5,pion/rtp,pion/interceptor), a Postgres driver, a JWT library, a WebSocket library, and four provider SDKs. Every one of those parses input from the network, and two of them — the ICE/DTLS path andgolang-jwt— parse input from unauthenticated strangers. Nothing tells the repo when one of them ships a CVE.The Docker image has the same hole and a wider one: the runtime stage is
node:22-bookworm-slim, it installstsxglobally, creates a Python venv, and runsnpm installacross every plugin directory. That is three ecosystems of transitive dependencies in the published image, and nothing scans it.For a project asking people to run it as infrastructure, each of these is a one-file addition, and their absence is more conspicuous than any single one of them.
Proposed change
Four separate, independently mergeable pieces.
golangci-lintis deliberately excluded here because #27 already covers it.1.
govulncheckin CI.golang/govulncheck-action, on PRs and pushes tomain. It reports only vulnerabilities in code paths actually reachable from this module, so the false-positive rate is low enough to gate on rather than merely report.2. Dependabot.
.github/dependabot.ymlwith four ecosystems:gomod(root),github-actions,npm(theplugins/directories), andpip(the Python plugin venv built in the Dockerfile). Group patch and minor updates into one weekly PR per ecosystem — ungrouped Dependabot on a repo with this many dependencies produces enough noise to get muted, which is the same as not having it.Pin the Pion packages to a separate group and do not auto-merge them. A minor bump in the media stack is a real behavioural change on a latency-sensitive path, and CI cannot tell you whether audio still sounds right.
3. Image scanning. Trivy or Grype against the built image in the release/publish workflow, failing on HIGH and CRITICAL with a documented allowlist file for anything that is genuinely unfixable in
node:22-bookworm-slim. Upload SARIF so findings land in the Security tab instead of only in a log.4. SBOM.
syftoranchore/sbom-actionattaching a CycloneDX SBOM to each release. Cheap, and it is the first thing anyone doing vendor review asks for.Worth doing at the same time, since it is the same category: a
SECURITY.mdsupported-versions table (the file exists but predates any release), and enabling GitHub's secret scanning and push protection on the repo.Acceptance criteria
govulncheckruns on every PR and fails the build on a reachable vulnerability..github/dependabot.ymlcoversgomod,github-actions,npm,pip, with grouped updates and Pion held separate.Pointers
.github/workflows/ci.yml— wheregovulncheckslots in as a step or a parallel jobgo.mod— the dependency set being coveredDockerfile— runtime stage L16 onward, the npm/pip installs that scanning targetsSECURITY.md— supported-versions table to add