From 0010894f99a68eeff7bf39b972e0cf369c2a7346 Mon Sep 17 00:00:00 2001 From: Ricardo-binZzz <285964759+Ricardo-binZzz@users.noreply.github.com> Date: Wed, 29 Jul 2026 07:29:26 +0800 Subject: [PATCH] fix(deploy): prevent application privilege gains --- .github/workflows/backend-ci.yml | 1 + deploy/docker-compose.dev.yml | 2 + deploy/docker-compose.local.yml | 2 + deploy/docker-compose.standalone.yml | 2 + deploy/docker-compose.yml | 2 + deploy/tests/docker-compose-security-test.sh | 44 ++++++++++++++++++++ 6 files changed, 53 insertions(+) create mode 100755 deploy/tests/docker-compose-security-test.sh diff --git a/.github/workflows/backend-ci.yml b/.github/workflows/backend-ci.yml index b917344959..77729863df 100644 --- a/.github/workflows/backend-ci.yml +++ b/.github/workflows/backend-ci.yml @@ -16,6 +16,7 @@ jobs: run: | /bin/bash -n deploy/apple-container.sh /bin/bash deploy/tests/apple-container-test.sh + /bin/sh deploy/tests/docker-compose-security-test.sh /bin/sh deploy/test-caddyfile-cache.sh test: diff --git a/deploy/docker-compose.dev.yml b/deploy/docker-compose.dev.yml index db00ac9de8..8603f121db 100644 --- a/deploy/docker-compose.dev.yml +++ b/deploy/docker-compose.dev.yml @@ -17,6 +17,8 @@ services: NPM_CONFIG_REGISTRY: ${NPM_CONFIG_REGISTRY:-https://registry.npmmirror.com} container_name: sub2api-dev restart: unless-stopped + security_opt: + - no-new-privileges:true ports: - "${BIND_HOST:-127.0.0.1}:${SERVER_PORT:-8080}:8080" volumes: diff --git a/deploy/docker-compose.local.yml b/deploy/docker-compose.local.yml index 364fcc2ecc..588862e2f2 100644 --- a/deploy/docker-compose.local.yml +++ b/deploy/docker-compose.local.yml @@ -27,6 +27,8 @@ services: image: weishaw/sub2api:latest container_name: sub2api restart: unless-stopped + security_opt: + - no-new-privileges:true ulimits: nofile: soft: 100000 diff --git a/deploy/docker-compose.standalone.yml b/deploy/docker-compose.standalone.yml index 04a46a8dd5..cd0a008871 100644 --- a/deploy/docker-compose.standalone.yml +++ b/deploy/docker-compose.standalone.yml @@ -15,6 +15,8 @@ services: image: weishaw/sub2api:latest container_name: sub2api restart: unless-stopped + security_opt: + - no-new-privileges:true ulimits: nofile: soft: 100000 diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 3e1e69a895..68a51e78dd 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -19,6 +19,8 @@ services: image: weishaw/sub2api:latest container_name: sub2api restart: unless-stopped + security_opt: + - no-new-privileges:true ulimits: nofile: soft: 100000 diff --git a/deploy/tests/docker-compose-security-test.sh b/deploy/tests/docker-compose-security-test.sh new file mode 100755 index 0000000000..b6cfe768da --- /dev/null +++ b/deploy/tests/docker-compose-security-test.sh @@ -0,0 +1,44 @@ +#!/bin/sh +set -eu + +repo_root=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd) +cd "$repo_root" + +check_application_security_opt() { + file=$1 + count=$( + awk ' + $0 == " sub2api:" { + in_application = 1 + next + } + in_application && $0 ~ /^ [A-Za-z0-9_-]+:$/ { + in_application = 0 + } + in_application && $0 == " security_opt:" { + in_security_opt = 1 + next + } + in_application && in_security_opt && $0 == " - no-new-privileges:true" { + count++ + } + END { print count + 0 } + ' "$file" + ) + + if [ "$count" -ne 1 ]; then + printf '%s must enable no-new-privileges exactly once for the sub2api service\n' "$file" >&2 + exit 1 + fi +} + +for compose_file in \ + deploy/docker-compose.yml \ + deploy/docker-compose.local.yml \ + deploy/docker-compose.standalone.yml \ + deploy/docker-compose.dev.yml +do + check_application_security_opt "$compose_file" +done + +printf 'docker compose security test passed\n'