AI Coding Agents
Security
How to harden container images without breaking them
September 25, 2026 - 4 minute read
AI Coding Agents
Security
September 25, 2026 - 4 minute read
To harden a container image safely, start from one scanner finding, make the smallest change that removes it, then rebuild without cache, scan the new digest again, and run the image with its production entrypoint. A coding agent can do this repository work when each step leaves evidence in the pull request.
Container image hardening removes unnecessary software and limits what a compromised workload can do. Coding agents can handle much of the repository work, but a broad instruction such as “secure this image” invites unrelated upgrades and makes the result hard to verify. A useful task starts with a specific finding and ends with a rebuilt, tested image.
Docker’s build best practices explain how base-image selection and multi-stage builds limit what reaches the runtime image. Apply the controls relevant to the finding instead of combining every possible hardening change in one patch.
Begin with the image digest, Dockerfile path, build command, target architecture, and scanner finding. Record the affected package and the layer that introduced it. A vulnerable operating-system package may come from the base image, while an application dependency may be installed later. The repair path differs.
Give the agent an explicit boundary. It may update a base image digest, remove an unused package, split build and runtime stages, or set a non-root user. It should leave deployment configuration and unrelated application dependencies unchanged unless the finding requires them.
Each kind of change has its own way of breaking a working image. The table pairs the common hardening edits with what to check after the rebuild.
| Change | What to verify after the rebuild |
|---|---|
| Update the base image digest | New findings from the replacement base, certificate loading, native libraries |
| Remove an unused package | Startup, background work, and any path that called the package |
| Split build and runtime stages | Copied artifacts, entrypoint, and health check |
| Set a non-root user | Filesystem permissions and port bindings |
| Remove the shell or package manager | Health checks and runbooks that assumed them |
Preserve a rollback point before editing. Record the prior digest and the command that produced the current image. This allows reviewers to compare artifacts and restore the known build if runtime tests uncover a compatibility problem.
Rebuild without relying on a developer’s local cache, then scan the resulting digest rather than the Dockerfile alone. Confirm that the targeted finding is gone and inspect any new findings introduced by the replacement base. A smaller package count can reduce attack surface, but package count by itself does not prove that an image is secure.
Run the image with its production entrypoint and the same user, filesystem, port, and health-check assumptions used in deployment. Exercise startup, shutdown, network access, certificate loading, and any native libraries. Removing a shell or package manager may be appropriate for runtime, but only after tests show the service does not depend on it.
The pull request should name the original finding, old and new image digests, changed layers, build command, scanner command, and runtime tests. Include the reason for every package removal or privilege change. Avoid pasting credentials, complete environment dumps, or private registry tokens into logs.
Reviewers need to distinguish a source fix from a scanner exception. If remediation is unavailable, document the affected component, reachability, compensating control, owner, and expiration date. An unbounded ignore rule hides future findings.
Keep the repair tied to the finding and show how the rebuilt image addresses it. Reviewers can then assess the runtime consequences without separating an unrelated application refactor from the security change.
Factory is a platform for running a software factory, where agents called Droids take work from a signal to a reviewed pull request. A scanner finding on a container image is that kind of signal, and the work after it follows the same path each time.
Run the edit in CI with Droid Exec. Droid Exec is Factory's headless mode. Each run is a single non-interactive pass that is read-only by default. --auto low allows file edits but blocks package installs and test runs, and --auto medium adds builds, tests, and local git operations. The dependency scan recipe shows a three-job layout where no credential is present while dependency or test code runs, a pattern that fits image rebuilds too.
Start from the finding. Factory Automations can start a Droid on a schedule or on a GitHub event, such as a push to a branch. Webhook triggers, which let a scanner post findings directly, are in private preview.
Review the change. Factory's security review checks the pull request against STRIDE, OWASP, and supply chain risks in two passes, candidates first and validation second. Deterministic image scanning and runtime tests stay as separate required checks because each answers a different question.
Container image hardening removes unnecessary software from an image and limits what a compromised workload can do. Common changes are a newer base image digest, removing unused packages, multi-stage builds, and a non-root user.
Start from a specific scanner finding with the image digest, Dockerfile path, build command, target architecture, and the layer that introduced the package. Limit the edit to what the finding requires and leave deployment configuration alone.
Rebuild without the local cache, scan the resulting digest, confirm the target finding is gone, and inspect new findings. Then run the image with its production entrypoint, user, ports, and health check.
Droid Exec can run the bounded edit in CI with an explicit autonomy level, Automations can start the work on a schedule or GitHub event, and Factory security review checks the pull request before an owner merges it.
Discuss your team’s software development, privacy, or deployment requirements.
Start building