Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .trivy/pgedge-control-plane.trivyignore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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."
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."
18 changes: 18 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions changes/unreleased/Security-20260717-040124.yaml
Original file line number Diff line number Diff line change
@@ -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
6 changes: 5 additions & 1 deletion docker/control-plane-ci/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"]
6 changes: 5 additions & 1 deletion docker/control-plane-dev/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.25.8
FROM golang:1.26.5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Run the container as a non-root user.

Trivy reports that this image runs as root. Create a dedicated unprivileged user and add a USER directive before the entrypoint; otherwise the security refresh still ships a container with unnecessary privilege.

Proposed fix
 FROM golang:1.26.5
+RUN useradd --system --uid 10001 app
+USER app
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FROM golang:1.26.5
FROM golang:1.26.5
RUN useradd --system --uid 10001 app
USER app
🧰 Tools
🪛 Trivy (0.72.0)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docker/control-plane-dev/Dockerfile` at line 1, Update the Dockerfile to
create a dedicated unprivileged user, ensure required application files and
directories are accessible to that user, and add a USER directive selecting it
before the entrypoint so the container does not run as root.

Source: Linters/SAST tools


ENV CGO_ENABLED=0

Expand All @@ -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" ]
9 changes: 8 additions & 1 deletion docker/control-plane/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
FROM gcr.io/distroless/static-debian12
FROM gcr.io/distroless/static-debian12:latest@sha256:61b7ccecebc7c474a531717de80a94709d20547cdcdaf740c25876f2a8e38b44

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this digest a fat manifest (multi-arch) or platform-specific?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this image works on all the different chip types (Intel/AMD and ARM included), so it's fine


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 /
9 changes: 8 additions & 1 deletion docs/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
FROM squidfunk/mkdocs-material
FROM squidfunk/mkdocs-material:latest@sha256:51b87149d227691486b5f08993d28c65ca7e4990010664b697265b8e6fcd5287

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== docs/Dockerfile (numbered) ==\n'
cat -n docs/Dockerfile

printf '\n== repo files mentioning mkdocs-material or docs image usage ==\n'
rg -n --hidden --glob '!**/.git/**' 'mkdocs-material|docs/Dockerfile|squidfunk/mkdocs-material|USER ' .

printf '\n== docs directory file list ==\n'
git ls-files docs

Repository: pgEdge/control-plane

Length of output: 5862


🌐 Web query:

squidfunk/mkdocs-material default user root Dockerfile USER upstream image

💡 Result:

The official squidfunk/mkdocs-material Docker image runs as the root user by default [1][2]. Because the container executes commands as root, any files created or modified within a mounted volume (e.g., when running mkdocs new or building a site) will be owned by the root user on the host system [2]. To avoid file permission issues where generated files are owned by root, you can pass the current user's UID and GID to the container using the --user flag when running the docker command [2]: docker run --rm -it -v ${PWD}:/docs --user "$(id -u):$(id -g)" squidfunk/mkdocs-material build This configuration ensures that files created within the container are owned by your host user rather than the root user [2].

Citations:


Run the docs image as non-root. docs/Dockerfile:1 still inherits the upstream image’s default root user, so the container will run as root unless you add a USER after the package install or document an explicit runtime --user override.

🧰 Tools
🪛 Trivy (0.72.0)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/Dockerfile` at line 1, Update the docs Dockerfile after the package
installation steps to switch execution to a non-root USER, using an existing
non-root user provided by the squidfunk/mkdocs-material base image; otherwise
document an explicit runtime user override.

Source: Linters/SAST tools


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.