Skip to content

Security: stop the container cleanly and harden its runtime - #369

Merged
SandObserver merged 2 commits into
mainfrom
security/container-runtime-hardening
Oct 2, 2026
Merged

SandObserver merged 2 commits into
mainfrom
security/container-runtime-hardening

Conversation

@SandObserver

@SandObserver SandObserver commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • docker-entrypoint.sh: wait with || status=$? and loop while supervisord is alive. Under set -eu the wait interrupted by the TERM trap returned 143 and exited PID 1, so the kernel killed supervisord, nginx and the API mid-shutdown (02-1).
  • docker-compose.yml: add the KILL capability. Root supervisord cannot signal the API, which runs as node, without it; a stop logged unknown problem killing api ... Operation not permitted and the API died by SIGKILL.
  • Dockerfile: copy api/ and the shared ui/js modules without --chown=node:node, so the API cannot rewrite its own code (02-5).
  • exit-on-fatal.py, docker-entrypoint.sh, supervisord.conf: the fatal marker and supervisord's pid file move from /tmp to root-owned /run (02-6).
  • nginx/csp-api.conf: default-src 'none'; frame-ancestors 'none'; sandbox, included by the three /api/ locations, which did not inherit the server policy (02-7).
  • templates/stackyard.xml: ExtraParams with the Compose capabilities, no-new-privileges, --init, PID, memory and CPU limits (02-9), and the Compose NODE_OPTIONS heap cap so the memory limit does not kill the API.

Testing
All green, including the homelab Docker build and a throwaway container (clean stop exits 0, fatal path exits 1, /api/ CSP, root-owned /app). Added 5 entrypoint shutdown tests that run the real script (4 fail without the fix, under sh and dash) and tests for the /run paths, source ownership, the API policy, the template flags and the KILL capability.

Changelog

Fixed

  • Stop the container cleanly on docker stop instead of killing the dashboard mid-shutdown.

Security

  • Send a restrictive Content-Security-Policy on API responses.
  • Apply the Compose file's capability, privilege and resource limits to the Unraid template.

Checklist

  • Stays within the project constraints: one container, no runtime dependencies, no build step (see CONTRIBUTING.md).
  • Tests added or updated for new logic, and the full suite, lint, and typechecks pass.
  • Docs updated if behavior or configuration changed.

- Keep the entrypoint waiting while supervisord shuts down; set -e exited on the interrupted wait.
- Add the KILL capability to the Compose file so supervisord can signal the API.
- Copy the API source into the image owned by root.
- Write the fatal marker and supervisord pid file under /run instead of /tmp.
- Send a locked-down Content-Security-Policy on every /api/ response.
- Apply the Compose hardening to the Unraid template.
@SandObserver SandObserver added docker Pull requests that update docker code security Security fix labels Oct 2, 2026
@SandObserver
SandObserver merged commit 087b49d into main Oct 2, 2026
9 checks passed
@SandObserver
SandObserver deleted the security/container-runtime-hardening branch October 2, 2026 22:49
stackyard-release Bot pushed a commit that referenced this pull request Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docker Pull requests that update docker code security Security fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant