Skip to content

security: harden The Herald production container runtime #42

Description

@damienjburks

Summary

The Herald currently uses python:3.13-slim as the base for both its dependency and final runtime stages and installs curl into that shared base image. As a result, the production container includes a broader operating-system surface and package-management lineage than the application requires at runtime.

Harden the production container by moving the final runtime stage to a minimal non-root Python image while preserving application behavior and ECS health checks.

Current State

The current Dockerfile uses:

FROM python:3.13-slim AS base

RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    rm -rf /var/lib/apt/lists/*

The final stage inherits from that same base image.

Objective

Reduce the production container attack surface without changing The Herald's application behavior.

Requirements

  • Preserve Python 3.13 compatibility.
  • Preserve a multi-stage build.
  • Replace the final runtime stage with an appropriately minimal Python runtime image, preferably a Chainguard Python image if compatibility is validated.
  • Ensure the container runs as a non-root user.
  • Avoid installing a shell, package manager, compiler toolchain, or debugging utilities into the production image solely for convenience.
  • Rework the ECS/container health check so it does not require curl to exist in the final runtime image.
  • Confirm uvicorn starts successfully on port 8080.
  • Confirm The Herald can connect to Discord, retrieve Parameter Store values, access DynamoDB, and execute scheduled jobs.
  • Preserve CloudWatch logging.
  • Update documentation for any changed operational/debugging procedures.

Security Validation

Capture before/after vulnerability scan results for the final production image using Trivy or an equivalent image scanner.

Include at minimum:

Before:
Critical:
High:
Medium:
Low:

After:
Critical:
High:
Medium:
Low:

The PR should explain which runtime components were removed and how that reduces attack surface.

Acceptance Criteria

  • Production runtime no longer inherits from the current general-purpose Debian-based base stage.
  • Container runs as non-root.
  • curl is no longer required in the final runtime solely for health checking.
  • The image builds successfully.
  • /health remains usable by ECS health checks.
  • Discord connectivity and scheduled jobs continue to function.
  • Before/after vulnerability scan evidence is included in the PR.
  • No new HIGH or CRITICAL vulnerabilities are introduced.
  • Runtime attack-surface reduction is documented.

Contributor Guidance

Level: Beginner / Intermediate
Area: Container Security / Software Supply Chain

This is intended to be a practical introduction to production container hardening: preserve functionality while deliberately minimizing what ships in the runtime image.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions