Skip to content

feat: harden container with non-root execution and smoke tests - #201

Open
ashhadali10 wants to merge 5 commits into
OWASP:mainfrom
ashhadali10:feat/non-root-hardening
Open

ashhadali10 wants to merge 5 commits into
OWASP:mainfrom
ashhadali10:feat/non-root-hardening

Conversation

@ashhadali10

Copy link
Copy Markdown

Description

Implements the non-root container hardening portion of #109.

This PR makes the container drop privileges to a dedicated non-root user
(docksec, UID/GID 10001) for standalone docker run, while keeping root
for GitHub Docker container actions (required for GITHUB_WORKSPACE access).

  • Dockerfile: installed pinned Docker CLI static binary (Debian trixie no
    longer ships docker.io, so the previous install silently produced a broken
    image with docker: not found); created docksec user (UID/GID 10001);
    matched container docker group GID to the host socket GID at build time;
    pre-created /home/docksec/.docksec/results with correct ownership to fix
    PermissionError when writing reports as non-root; installed gosu for
    safe privilege dropping. USER is intentionally not set because GitHub
    Docker container actions must run as root to access GITHUB_WORKSPACE.
  • entrypoint.sh: drops privileges to docksec via gosu when running
    standalone; stays root when GITHUB_WORKSPACE is set (GitHub Action
    compatibility); users can override with docker run --user ....
  • tests/smoke-test-nonroot.sh: verifies standalone run drops privileges,
    CLI (--version / --help) works as non-root, GitHub Action mode stays
    root, and --user 0 override works.

Closes #109 (non-root + smoke tests portion)

Type of Change

  • New feature
  • Security fix
  • Test update
  • Build / CI configuration

How Has This Been Tested?

  • Unit tests
  • Manual testing

Test Configuration:

  • Python version: 3.12.15
  • Operating System: Ubuntu 22.04 (x86_64)
  • DockSec version: 2026.8.19

Test evidence:

  1. pytest tests/ — 546 passed, 153 subtests passed in 22.91s
  2. bash tests/smoke-test-nonroot.sh — all 4 tests pass:
    • Test 1: standalone run drops privileges ✅
    • Test 2: CLI works as non-root ✅
    • Test 3: GH Action mode stays root ✅
    • Test 4: --user 0 override works ✅
  3. Manual image build and scan of vulnerables/web-dvwa:latest succeeds,
    producing HTML and JSON reports under the mounted output directory.

Behaviour matrix:

Invocation Effective UID
docker run ... docksec 10001 (non-root, auto-drop)
docker run -e GITHUB_WORKSPACE=... docksec (Action) 0 (root)
docker run --user 0 docksec 0 (explicit override)
docker run --user 10001:10001 docksec 10001

Checklist

  • Code follows the style guidelines of this project
  • Self-review completed
  • Hard-to-understand areas are commented
  • Documentation updated where needed (no user-facing docs changed)
  • No new warnings or errors introduced
  • Tests added that prove the fix or feature works
  • All existing tests pass
  • Dependent changes have been merged and published (n/a)
  • Spelling checked

Screenshots (if applicable)

N/A — no UI changes.

Related Issues / PRs

Note on make check-test: Local black --check . reports 46 pre-existing
files that black would reformat. This is a version mismatch (black is
unpinned in pyproject.toml, so pip install -e ".[dev]" pulls a newer
version than the code was formatted with). No .py files are modified in
this PR, so this is unrelated to these changes.


By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

@github-actions github-actions Bot added docker Changes to Docker/container assets tests Changes to the test suite labels Oct 19, 2026
@pfarikrispy

Copy link
Copy Markdown

@ashhadali10 I think is really great work! Thanks. You were very thorough and structured. The UID/GUID handling is well thought out and marked with clear variables. The smoke test is excellent! very very nice.

My only remark would be that you are pulling in a binary from docker to install the docker CLI from a curl.
That's good but you do not verify the source nor the integrity of the binary archive.

Since this is a security tool, I think the source and integrity of any deps should be verified before installing. Right? This is often overlooked but these days that can become a costly mistake. Granted, docker.io is not just any source, but still.

@pfarikrispy

pfarikrispy commented Oct 25, 2026 •

Copy link
Copy Markdown

While searching for the docker cli tar.gz files, I found the official docker cli image. I couldn't find a clear way to check the source (via signatures) or integrity (via checksums).

@ashhadali10

Copy link
Copy Markdown
Author

While searching for the docker cli tar.gz files, I found the official docker cli image. I couldn't find a clear way to check the source (via signatures) or integrity (via checksums).

* Wouldn't it greatly simplify the Dockerfile by using a multi-layer build and simply copy the binary from the official image into the final layer?
  
  * See https://hub.docker.com/layers/library/docker/cli/images/sha256-98776017a505b6d89c0adff8c63b0d8701ca10280c41315dbb0638fe3b5cf6e5

* Alternatively, why don't you just install the docker CLI through `apt-get` from the official Ubuntu pkg repos, since these are signed with GPG.

Thanks @pfarikrispy for the kind words and for catching this you re right, and I appreciate the careful review.

You correctly identified a real supply-chain risk the previous Dockerfile fetched the Docker CLI as a tarball over curl without any signature or checksum verification. If the download had been tampered with, the image would have shipped a malicious binary a costly mistake for a security tool.

Fixed in 70bc9c4: the Docker CLI is now installed from Docker's official GPG-signed APT repository (docker-ce-cli), so apt verifies both source and integrity automatically. I went with your apt-get suggestion (Solution 2) because it gives us end-to-end GPG verification and keeps the build simple. I also looked at the multi-stage docker/cli image (Solution 1), but the apt-get path felt cleaner here.

Verified locally:

  • docker --version works as non root
  • dpkg -l docker-ce-cli confirms the package came from the APT repo (not a tarball)
  • pytest tests/ 546 passed
  • bash tests/smoke-test-nonroot.sh 4/4 pass (standalone drops privileges, GH Action mode stays root, --user 0 override works)

The CI workflows are still awaiting maintainer approval would you be able to approve them so the checks can run?

Thanks again for the thorough review.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docker Changes to Docker/container assets tests Changes to the test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Improve container security and harden your supply chain

2 participants