Privilege escalation (Docker container runtime hardening)

HIGH
rails/rails
Commit: f4aa567c6063
Affected: < 8.1.3
2026-04-05 12:15 UTC

Description

Summary of the change: The commit hardens the Dockerfile template and related test fixture to run the Rails application in a non-root context and to ensure runtime files are owned by a non-root user. Specifically: - The Dockerfile template now creates a non-root user (rails) and sets USER rails:rails for the runtime stage. - COPY commands in the final image use explicit ownership (COPY --from=build --chown=rails:rails). - The test fixture Dockerfile now mirrors the non-root runtime setup and adjusts file ownership accordingly. What this fixes: Running containers as root inside a production image is a common security risk, as root inside a container can potentially be abused to escalate privileges within the container, or to exploit host/kernel features if combined with other misconfigurations. By ensuring the runtime process runs as a non-root user and by binding file ownership to that user, the surface area for privilege escalation is reduced when using Rails’ Dockerfile templates. Scope and impact: This affects applications scaffolded via Rails generators that include the Dockerfile template (railties/lib/rails/generators/rails/app/templates/Dockerfile.tt) and the related test fixtures (railties/test/fixtures/Dockerfile.test). Since the tracked version is 8.1.3, prior versions (< 8.1.3) would benefit from this hardening if they used the affected templates. It is a security-hardening improvement rather than a change in Rails core functionality. Assessment: This is a genuine hardening change that mitigates privilege-escalation risk in containerized deployments by avoiding root execution in the runtime image and by tightening file ownership. It is not a behavioral security bug in Rails’ runtime logic, but it aligns with best practices for container security. The change is not a pure dependency bump; it alters template/fixture code to improve security posture.

Commit Details

Author: Jean Boussier

Date: 2026-03-13 08:42 UTC

Message:

Merge pull request #56967 from damln/optimize-dockerfile-build-performance Optimize generated Dockerfile build performance

Triage Assessment

Vulnerability Type: Privilege escalation

Confidence: HIGH

Reasoning:

The changes introduce non-root runtime usage for Docker image (setting USER rails:rails) and adjust file ownership via COPY --chown. These harden the image against privilege escalation and reduce risk of file permission issues, which are common security-hardening improvements in container builds.

Verification Assessment

Vulnerability Type: Privilege escalation (Docker container runtime hardening)

Confidence: HIGH

Affected Versions: < 8.1.3

Code Diff

diff --git a/railties/lib/rails/generators/rails/app/templates/Dockerfile.tt b/railties/lib/rails/generators/rails/app/templates/Dockerfile.tt index 8fce7d5510720..1747c3bfe628a 100644 --- a/railties/lib/rails/generators/rails/app/templates/Dockerfile.tt +++ b/railties/lib/rails/generators/rails/app/templates/Dockerfile.tt @@ -97,13 +97,14 @@ RUN bundle exec bootsnap precompile -j 1 app/ lib/ <% end -%> <% unless options.api? || skip_asset_pipeline? -%> # Precompiling assets for production without requiring secret RAILS_MASTER_KEY +<% if using_node? || using_bun? -%> +RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile && \ + rm -rf node_modules +<% else -%> RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile - <% end -%> -<% if using_node? || using_bun? -%> -RUN rm -rf node_modules -<% end %> +<% end -%> # Final stage for app image FROM base diff --git a/railties/test/fixtures/Dockerfile.test b/railties/test/fixtures/Dockerfile.test index 82c6d625fd1aa..0018577b5736e 100644 --- a/railties/test/fixtures/Dockerfile.test +++ b/railties/test/fixtures/Dockerfile.test @@ -45,15 +45,14 @@ FROM base # Clean up installation packages to reduce image size RUN rm -rf /var/lib/apt/lists /var/cache/apt/archives -# Copy built artifacts: gems, application -COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" -COPY --from=build /rails /rails - # Run and own only the runtime files as a non-root user for security -RUN useradd rails --create-home --shell /bin/bash && \ - chown -R rails:rails db log storage tmp +RUN useradd rails --create-home --shell /bin/bash USER rails:rails +# Copy built artifacts: gems, application +COPY --chown=rails:rails --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" +COPY --chown=rails:rails --from=build /rails /rails + # Entrypoint prepares the database. ENTRYPOINT ["/rails/bin/docker-entrypoint"]
← Back to Alerts View on GitHub →