Problem
Creating users without explicit flags can trigger UID-related side effects, especially with high UIDs and log-initialization behavior. This can bloat image layers and cause permission surprises. Action: define useradd flags explicitly, including -l where policy requires it.
Description
Container runtime security depends on predictable UID/GID mapping. Inconsistent identity creation breaks mounted volume ownership and runtime access checks. Action: standardize fixed UID/GID conventions across services and environments.
On some distributions, useradd without -l (--no-log-init) updates lastlog and faillog, which can inflate layers when very high UIDs are used. Action: use -l for high-UID service accounts to avoid unnecessary log-file growth.
Least-privilege runtime starts with deterministic user setup in the image build itself. Create the service account explicitly, set ownership, and switch to non-root before runtime layers. Action: make user creation a mandatory, reviewed part of Dockerfile standards.
Use this rollout checklist to prevent UID drift:
- Define
useraddflags explicitly, including fixed UID/GID values. - Use
-lfor high-UID accounts where log initialization is unnecessary. - Set file ownership at build time for runtime-required paths.
- Add CI checks that run as the created user and validate write access.
Treat verification as part of the rule, not optional cleanup. Action: automate a static check, a build check, and a runtime smoke check in the default CI pipeline so regressions are caught before review.
- Static check: fail when the disallowed pattern appears in Dockerfile or manifest.
- Build check: run a minimal image build to confirm the secure pattern is valid.
- Runtime check: start the workload and assert expected behavior with one deterministic probe.
Examples of code
Problematic code
FROM ubuntu:24.04
RUN useradd -u 198401 appuser
USER appuserVerified code
FROM ubuntu:24.04
RUN useradd -u 198401 -l -m appuser
USER appuser