Skip to content

Dockerfile.production: non-root test never runs and dependency install is unpinned + failure-swallowing #1121

Description

@groupthinking

Context

Two defects in the production container definition, found while verifying #1095. They compound: the second one is what hides the first.

1. test_dockerfile_uses_nonroot_user never runs (vacuous test)

tests/unit/test_security_fixes.py:195 resolves the Dockerfile at the repository root:

dockerfile = project_root / "Dockerfile.production"
if not dockerfile.exists():
    pytest.skip("Dockerfile.production not found")

The file does not live there — it is at infrastructure/docker/Dockerfile.production. So the test skips unconditionally:

$ pytest tests/unit/test_security_fixes.py -k dockerfile -rs
SKIPPED [1] tests/unit/test_security_fixes.py:195: Dockerfile.production not found
1 skipped, 12 deselected

The USER / non-root assertions have therefore never executed. A regression that reintroduced a root-running production image would pass CI silently. This is the same failure mode as #1116 — a test that reports success for a reason unrelated to the property it claims to verify.

SECURITY.md:53 documents the security build as docker build -t eventrelay:test -f Dockerfile.production ., which is also root-relative and therefore also stale.

2. Unpinned, failure-swallowing dependency install

infrastructure/docker/Dockerfile.production:28-30:

RUN pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org \
    fastapi uvicorn pytest python-dotenv pydantic aiofiles httpx requests python-multipart || \
    echo "Warning: Some packages may not be available in constrained environments"

Three problems:

  • No version constraints on any of the nine packages. This install path does not read requirements.txt, so the python-multipart>=0.0.31 floor added by fix(deps): raise python-multipart floor to a patched release #1092 for advisories 468–471 does not apply here. Any pinned, constrained, or cached resolve can select a vulnerable build. This is precisely the failure mode Execution: raise python-multipart floor past advisories 468–471 (PR #1092) #1095 was opened to prevent, in a file that issue's definition of done did not cover.
  • || echo swallows every failure. A build in which pip install fails outright still exits 0, producing an image that passes docker build and then dies at runtime with ModuleNotFoundError. The health check at line 37 would fail, but only after deploy.
  • pytest is installed into the production image, enlarging the runtime attack surface with test tooling.

Impact

No active exploit: no CI workflow builds this file, and scripts/deployment/one-click-deploy.sh:104 passes -f Dockerfile.production from the repo root, so that build path is currently broken. The exposure is latent — the moment anyone corrects the path (which is the natural fix for the stale reference), an unpinned, failure-swallowing, root-verified-by-nobody image becomes buildable.

Definition of done

  • test_dockerfile_uses_nonroot_user resolves the real path and executes its assertions rather than skipping; a deliberately root-running Dockerfile must make it fail.
  • The test fails loudly if the Dockerfile is missing, rather than skipping, so a future move cannot silently re-vacate it.
  • Every package in the Dockerfile.production install list carries a floor consistent with the declarations in requirements.txt / pyproject.toml, in particular python-multipart>=0.0.31.
  • The install no longer masks failure with || echo.
  • pytest is not installed into the production image.
  • Stale root-relative Dockerfile.production references are corrected.
  • tests/unit/ shows no regression versus the origin/main baseline.

Activity

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

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions