diff --git a/.trivy/pgedge-control-plane.trivyignore.yaml b/.trivy/pgedge-control-plane.trivyignore.yaml index 481a6b77..640518ef 100644 --- a/.trivy/pgedge-control-plane.trivyignore.yaml +++ b/.trivy/pgedge-control-plane.trivyignore.yaml @@ -12,4 +12,4 @@ vulnerabilities: - id: CVE-2026-41568 statement: "docker cp race-condition DoS (moby/moby) — same unfixed v27.x dependency and same unused code path as CVE-2026-41567/CVE-2026-42306 (no CopyToContainer/CopyFromContainer/archive API usage anywhere in the repo). Risk accepted; revisit if a v27.x backport or a migration to moby/moby v2 lands." - id: GO-2026-5932 - statement: "golang.org/x/crypto/openpgp is unmaintained/unsafe-by-design — not applicable, this codebase never imports x/crypto/openpgp (verified via repo-wide grep); x/crypto is used only for ssh/bcrypt/other subpackages." \ No newline at end of file + statement: "golang.org/x/crypto/openpgp is unmaintained/unsafe-by-design — not applicable, this codebase never imports x/crypto/openpgp (verified via repo-wide grep); x/crypto is used only for ssh/bcrypt/other subpackages." diff --git a/.trivyignore b/.trivyignore new file mode 100644 index 00000000..471a08be --- /dev/null +++ b/.trivyignore @@ -0,0 +1,18 @@ +# DS-0002: "Specify at least 1 USER command in Dockerfile with non-root user" +# +# Every Dockerfile in this repo (docker/control-plane, docker/control-plane-dev, +# docker/control-plane-ci) intentionally runs as root: the control-plane +# process manages ownership (chown) of bind-mounted Postgres/Patroni data, +# config, and cert directories on behalf of arbitrary database-owner +# UIDs/GIDs, which requires root privileges. The distroless static base used +# in production also has no shell/su-exec to drop privileges after that setup. +# See the matching `# nosemgrep: dockerfile.security.missing-user-entrypoint` +# comments in each Dockerfile for the same rationale. +# +# NOTE: inline `# trivy:ignore:DS-0002` comments do NOT suppress this check +# (verified empirically — DS-0002 is a whole-file "is USER present anywhere" +# check, not a line-specific one, so Trivy's line-scoped ignore-comment +# mechanism doesn't apply to it). This global entry is the only form that +# actually works; per-path scoping (`path:DS-0002` or a paths: list in +# .trivyignore.yaml) was tested and does not suppress the finding either. +DS-0002 diff --git a/changes/unreleased/Security-20260717-040124.yaml b/changes/unreleased/Security-20260717-040124.yaml new file mode 100644 index 00000000..b3f4f672 --- /dev/null +++ b/changes/unreleased/Security-20260717-040124.yaml @@ -0,0 +1,3 @@ +kind: Security +body: Update vulnerable dependencies (pgx v5.10.0, OpenTelemetry v1.44.0, golang.org/x/crypto v0.54.0, golang.org/x/net v0.57.0) and bump the Go toolchain to 1.26.5 to remediate Trivy-flagged CVEs in the control-plane image (PLAT-686). github.com/docker/docker CVE-2026-41567/CVE-2026-42306 have no fix in the v27.x line in use; risk-accepted in .trivy/pgedge-control-plane.trivyignore.yaml since the vulnerable docker-cp/archive-copy code paths are never invoked by this codebase. +time: 2026-07-17T04:01:24.289511+05:00 diff --git a/docker/control-plane-ci/Dockerfile b/docker/control-plane-ci/Dockerfile index 2aa072eb..006c8072 100644 --- a/docker/control-plane-ci/Dockerfile +++ b/docker/control-plane-ci/Dockerfile @@ -1,10 +1,14 @@ FROM debian:12 RUN apt-get update && \ - apt-get install -y curl && \ + apt-get install -y --no-install-recommends curl && \ rm -rf /var/lib/apt/lists/* COPY ./pgedge-control-plane /pgedge-control-plane # nosemgrep: dockerfile.security.missing-user-entrypoint.missing-user-entrypoint +# CI-only image; runs as root by design, same reasoning as the production +# Dockerfile (bind-mount ownership management). Trivy's DS-0002 is suppressed +# repo-wide in .trivyignore since inline ignore comments don't work for this +# whole-file check. ENTRYPOINT ["/pgedge-control-plane"] diff --git a/docker/control-plane-dev/Dockerfile b/docker/control-plane-dev/Dockerfile index ff2cb4c9..d25ce518 100644 --- a/docker/control-plane-dev/Dockerfile +++ b/docker/control-plane-dev/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.25.8 +FROM golang:1.26.5 ENV CGO_ENABLED=0 @@ -8,4 +8,8 @@ COPY ./entrypoint.sh /entrypoint.sh COPY ./pgedge-control-plane /pgedge-control-plane # nosemgrep: dockerfile.security.missing-user-entrypoint.missing-user-entrypoint +# Dev-only image; runs as root by design, same reasoning as the production +# Dockerfile (bind-mount ownership management). Trivy's DS-0002 is suppressed +# repo-wide in .trivyignore since inline ignore comments don't work for this +# whole-file check. ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/docker/control-plane/Dockerfile b/docker/control-plane/Dockerfile index 0c0cb941..ccd8c0b5 100644 --- a/docker/control-plane/Dockerfile +++ b/docker/control-plane/Dockerfile @@ -1,10 +1,17 @@ -FROM gcr.io/distroless/static-debian12 +FROM gcr.io/distroless/static-debian12:latest@sha256:61b7ccecebc7c474a531717de80a94709d20547cdcdaf740c25876f2a8e38b44 ARG TARGETOS ARG TARGETARCH ARG ARCHIVE_VERSION # nosemgrep: dockerfile.security.missing-user-entrypoint.missing-user-entrypoint +# Runs as root by design: the control-plane process manages bind-mounted host +# directories and files on behalf of arbitrary database owner UIDs/GIDs (chown, +# permission setup for Postgres/Patroni data dirs and certs), which requires +# root privileges. Distroless static has no shell/su-exec to safely drop +# privileges after that setup either. Trivy's DS-0002 (non-root user) is +# suppressed repo-wide in .trivyignore since inline ignore comments don't work +# for this whole-file check. ENTRYPOINT ["/pgedge-control-plane"] ADD pgedge-control-plane_${ARCHIVE_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz / diff --git a/docs/Dockerfile b/docs/Dockerfile index 73d95d7a..eb525cef 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,3 +1,10 @@ -FROM squidfunk/mkdocs-material +FROM squidfunk/mkdocs-material:latest@sha256:51b87149d227691486b5f08993d28c65ca7e4990010664b697265b8e6fcd5287 RUN pip install pymdown-extensions mkdocs-redoc-tag mkdocs-github-admonitions-plugin + +# No USER directive: `make docs` bind-mounts the whole repo (-v ${PWD}:/docs) +# with no UID mapping, and the host directory's owning UID varies per +# developer/CI runner. Baking in a fixed non-root UID risks permission-denied +# reads of the bind-mounted docs on any host whose UID doesn't match. Trivy's +# DS-0002 (non-root user) is suppressed repo-wide in .trivyignore for the same +# reason as the other Dockerfiles in this repo.