From 1ba5d638c85eb94320bfb90083755c3094baefd5 Mon Sep 17 00:00:00 2001 From: ttlequals0 Date: Fri, 15 May 2026 19:07:23 -0400 Subject: [PATCH] fix(2.4.8): replace gosu with setpriv to clear 50 Go stdlib CVEs Ubuntu 24.04 ships gosu 1.17 compiled against Go stdlib 1.22.2, which carries 50 known CVEs (3 CRITICAL, 19 HIGH, 26 MEDIUM, 2 LOW) per Docker Scout. setpriv from util-linux is already in the base image, has no Go runtime, and is the upstream-recommended gosu alternative. entrypoint.sh privilege-drop flags match gosu defaults: --reuid=minuspod --regid=minuspod --init-groups --inh-caps=-all Mirrored across GPU Dockerfile, CPU Dockerfile, both docker-compose files, and README. The 2 remaining torch CVEs (local DoS, LOW + MED) need a torch 2.6.0 -> 2.8.0 bump and are tracked separately. --- CHANGELOG.md | 6 ++++++ Dockerfile | 10 +++++----- Dockerfile.cpu | 10 +++++----- README.md | 2 +- docker-compose.cpu.yml | 2 +- docker-compose.yml | 2 +- entrypoint.sh | 7 ++++--- openapi.yaml | 2 +- version.py | 2 +- 9 files changed, 25 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80576a8a..9e709fc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.4.8] - 2026-05-15 + +### Security + +- **Replaced `gosu` with `setpriv` in `entrypoint.sh` and dropped the `gosu` package from both GPU and CPU images.** Clears 50 Go stdlib CVEs (3 CRITICAL, 19 HIGH, 26 MEDIUM, 2 LOW) that Ubuntu 24.04's `gosu 1.17` carries because it was compiled against Go stdlib 1.22.2. `setpriv` ships with `util-linux` in the base image, has no Go runtime, and is the upstream-recommended gosu alternative. The privilege-drop flags match gosu's defaults: `--reuid=minuspod --regid=minuspod --init-groups --inh-caps=-all`. The two remaining torch CVEs (local DoS, LOW + MEDIUM) need a torch 2.6.0 -> 2.8.0 upgrade and are tracked separately. + ## [2.4.7] - 2026-05-15 ### Changed diff --git a/Dockerfile b/Dockerfile index 6fbe2d8a..29d051aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,8 +30,9 @@ FROM nvidia/cuda:12.9.1-runtime-ubuntu24.04 # Install Python 3.11 from deadsnakes PPA and system dependencies # Ubuntu 24.04 ships Python 3.12; we use deadsnakes to keep Python 3.11 -# gosu is used by entrypoint.sh to drop privileges after the root-only -# chown step that migrates the data volume on first boot. +# setpriv (from util-linux, present in the base image) is used by +# entrypoint.sh to drop privileges after the root-only chown step that +# migrates the data volume on first boot. RUN apt-get update && apt-get install -y --no-install-recommends \ software-properties-common \ && add-apt-repository ppa:deadsnakes/ppa \ @@ -41,7 +42,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3.11-venv \ ffmpeg \ curl \ - gosu \ libsndfile1 \ libchromaprint-tools \ && apt-get upgrade -y \ @@ -49,7 +49,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ /usr/lib/python3/dist-packages/PyJWT* \ /usr/lib/python3/dist-packages/jwt* \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ - && gosu nobody true + && setpriv --reuid=nobody --regid=nogroup --init-groups true # Set python3.11 as default, create venv for all pip installs # Venv avoids pip 26+ "uninstall-no-record-file" errors with system packages @@ -108,7 +108,7 @@ COPY entrypoint.sh /app/ # Set permissions - use find to recursively set permissions on subdirectories # IMPORTANT: glob pattern *.py does NOT match files in subdirectories! # Create a non-root minuspod user (UID/GID 1000) that entrypoint.sh drops -# privileges to via gosu. The container still starts as root so the +# privileges to via setpriv. The container still starts as root so the # entrypoint can chown the data volume on first boot; no app code runs # as root. UID/GID are overridable at runtime with APP_UID/APP_GID. RUN find ./src -type f -name '*.py' -exec chmod 644 {} \; && \ diff --git a/Dockerfile.cpu b/Dockerfile.cpu index 688b7941..61cd29d3 100644 --- a/Dockerfile.cpu +++ b/Dockerfile.cpu @@ -53,8 +53,9 @@ FROM ubuntu:24.04 # Install Python 3.11 from deadsnakes PPA and system dependencies # Ubuntu 24.04 ships Python 3.12; we use deadsnakes to keep Python 3.11 -# gosu is used by entrypoint.sh to drop privileges after the root-only -# chown step that migrates the data volume on first boot. +# setpriv (from util-linux, present in the base image) is used by +# entrypoint.sh to drop privileges after the root-only chown step that +# migrates the data volume on first boot. RUN apt-get update && apt-get install -y --no-install-recommends \ software-properties-common \ && add-apt-repository ppa:deadsnakes/ppa \ @@ -64,7 +65,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3.11-venv \ ffmpeg \ curl \ - gosu \ libsndfile1 \ libchromaprint-tools \ && apt-get upgrade -y \ @@ -72,7 +72,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ /usr/lib/python3/dist-packages/PyJWT* \ /usr/lib/python3/dist-packages/jwt* \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ - && gosu nobody true + && setpriv --reuid=nobody --regid=nogroup --init-groups true # Set python3.11 as default, create venv for all pip installs # Venv avoids pip 26+ "uninstall-no-record-file" errors with system packages @@ -133,7 +133,7 @@ COPY entrypoint.sh /app/ # Set permissions - use find to recursively set permissions on subdirectories # IMPORTANT: glob pattern *.py does NOT match files in subdirectories! # Create a non-root minuspod user (UID/GID 1000) that entrypoint.sh drops -# privileges to via gosu. The container still starts as root so the +# privileges to via setpriv. The container still starts as root so the # entrypoint can chown the data volume on first boot; no app code runs # as root. UID/GID are overridable at runtime with APP_UID/APP_GID. RUN find ./src -type f -name '*.py' -exec chmod 644 {} \; && \ diff --git a/README.md b/README.md index 8a21030b..04687ea3 100644 --- a/README.md +++ b/README.md @@ -1297,7 +1297,7 @@ All data is stored in the `./data` directory: ### Container user -Runs as UID 1000 (`minuspod`). First boot chowns the data volume, then drops privileges via `gosu`. Override with `APP_UID` / `APP_GID` if your host volume belongs to a different UID, or bypass entirely with `docker run --user `. +Runs as UID 1000 (`minuspod`). First boot chowns the data volume, then drops privileges via `setpriv` (from `util-linux`, present in the base image). Override with `APP_UID` / `APP_GID` if your host volume belongs to a different UID, or bypass entirely with `docker run --user `. ### Database backup sensitivity diff --git a/docker-compose.cpu.yml b/docker-compose.cpu.yml index 52887722..e3068cec 100644 --- a/docker-compose.cpu.yml +++ b/docker-compose.cpu.yml @@ -25,7 +25,7 @@ services: # dockerfile: Dockerfile.cpu platform: linux/amd64 # The container ships a non-root `minuspod` user at UID/GID 1000 - # (entrypoint.sh drops root via gosu after fixing volume ownership). + # (entrypoint.sh drops root via setpriv after fixing volume ownership). # Override here to pin a specific APP_UID/APP_GID if your volume is # owned by a different user -- e.g. `user: "2000:2000"`. # user: "1000:1000" diff --git a/docker-compose.yml b/docker-compose.yml index 33d68186..5e56811c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ services: image: ttlequals0/minuspod:${MINUSPOD_VERSION:-latest} platform: linux/amd64 # The container ships a non-root `minuspod` user at UID/GID 1000 - # (entrypoint.sh drops root via gosu after fixing volume ownership). + # (entrypoint.sh drops root via setpriv after fixing volume ownership). # Override here to pin a specific APP_UID/APP_GID if your volume is # owned by a different user -- e.g. `user: "2000:2000"`. Leave unset # to use the image default (1000:1000). diff --git a/entrypoint.sh b/entrypoint.sh index e0018355..45d745dc 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -6,8 +6,8 @@ # from a host path owned by a different UID (common on first run after a # docker compose pull, or after an operator recreates the volume). We fix # ownership, then drop privileges to the unprivileged minuspod user via -# gosu. Only root needs to live long enough to run this script; gunicorn -# runs as UID 1000 (or APP_UID / APP_GID if overridden). +# setpriv (util-linux). Only root needs to live long enough to run this +# script; gunicorn runs as UID 1000 (or APP_UID / APP_GID if overridden). # set -euo pipefail @@ -47,7 +47,8 @@ if [[ "$(id -u)" == "0" ]]; then chown "${APP_UID}:${APP_GID}" /app/gunicorn.conf.py 2>/dev/null || true cd /app/src - exec gosu minuspod gunicorn -c /app/gunicorn.conf.py main_app:app + exec setpriv --reuid=minuspod --regid=minuspod --init-groups --inh-caps=-all -- \ + gunicorn -c /app/gunicorn.conf.py main_app:app fi # Non-root invocation path (operator used --user). Run directly. diff --git a/openapi.yaml b/openapi.yaml index 80b1b351..d737e2db 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -12,7 +12,7 @@ info: - Monitor system status and trigger cleanup operations - Manage cross-episode ad patterns with network and podcast scope - Submit corrections to improve ad detection accuracy - version: 2.4.7 + version: 2.4.8 contact: name: MinusPod license: diff --git a/version.py b/version.py index 999d130b..6ce19833 100644 --- a/version.py +++ b/version.py @@ -1 +1 @@ -__version__ = "2.4.7" +__version__ = "2.4.8"