Container Escape in Hanami (Ruby)
Container Escape in Hanami with Ruby — how this specific combination creates or exposes the vulnerability
Hanami, a modular Ruby web framework, encourages separation of concerns through its slice architecture and reliance on dry-system for dependency injection. When deployed in containerized environments (e.g., Docker, Kubernetes), misconfigurations in file permissions, volume mounts, or privileged flags can lead to container escape — where an attacker breaks out of the container to access the host system. In Hanami applications, this risk is amplified when Ruby code inadvertently exposes host paths or executes privileged operations due to overly permissive runtime settings.
For example, a Hanami action that uses FileUtils to manipulate files based on user input without proper path validation might allow directory traversal to /host if the container mounts the host’s root filesystem. Consider a route that serves user-uploaded files:
# apps/web/actions/users/avatar_update.rb
module Web::Actions::Users
class AvatarUpdate < Web::Action
include Deps['storage.avatar']
def handle(params, user)
avatar_file = params[:avatar][:tempfile]
# Unsafe: uses user-provided filename directly
filename = params[:avatar][:filename]
storage.avatar.store(filename, avatar_file.read)
end
end
end
If storage.avatar.store eventually calls File.join(base_path, filename) and filename contains ../../../host/etc/passwd, and the container mounts /host to the actual host root, the attacker can write or read host files. This is not a flaw in Hanami itself but emerges from the combination of Ruby’s file I/O flexibility, insufficient input validation in application code, and dangerous container configurations (e.g., --privileged, v /:/host).
Attackers may also exploit Ruby’s DL or Fiddle modules to invoke syscalls directly if $SAFE is misused or disabled, though this is less common in modern Hanami apps. The real danger lies in unintended host path exposure via volume mounts combined with path traversal in Ruby code — a scenario middleBrick detects by scanning for unauthenticated endpoints that leak filesystem access or respond with host-specific data.
Ruby-Specific Remediation in Hanami — concrete code fixes
To prevent container escape vectors in Hanami applications, focus on input validation, path sanitization, and least-privilege container deployment — not framework changes, as Hanami is secure by design when used correctly. The fix begins with validating and sanitizing file names in Ruby code before they reach storage layers.
Replace unsafe filename handling with an allowlist-based approach using Ruby’s Pathname and File utilities:
# apps/web/actions/users/avatar_update.rb
module Web::Actions::Users
class AvatarUpdate < Web::Action
include Deps['storage.avatar']
ALLOWED_EXTENSIONS = %w[.jpg .jpeg .png .gif].freeze
def handle(params, user)
avatar_file = params[:avatar][:tempfile]
filename = params[:avatar][:filename]
# Validate filename: only allow basename with safe extension
unless filename.match?(/\A[\w\-.]+\z/) && ALLOWED_EXTENSIONS.any? { |ext| filename.end_with?(ext) }
halt 422, { error: 'Invalid filename' }.to_json
end
# Further sanitize: remove path separators, use basename
safe_filename = File.basename(filename)
storage.avatar.store(safe_filename, avatar_file.read)
end
end
end
This ensures that even if the container mounts /host, the stored file is confined to the intended directory. Additionally, use Hanami’s validations block for declarative input checks:
# apps/web/actions/users/avatar_update.rb
module Web::Actions::Users
class AvatarUpdate < Web::Action
include Deps['storage.avatar']
params do
required(:avatar).hash do
required(:tempvalue).filled
required(:filename).filled(:string, format?: /\A[\w\-.]+\.(jpg|jpeg|png|gif)\z/i)
end
end
def handle(params, user)
# params are validated; safe to use
storage.avatar.store(params[:avatar][:filename], params[:avatar][:tempfile].read)
end
end
end
Finally, harden the container: run as non-root, drop unnecessary capabilities, avoid mounting host directories, and use read-only filesystems where possible. middleBrick identifies risky endpoints that could lead to such escapes by testing for path traversal, unexpected file access, and information leakage — guiding developers to apply these Ruby-specific fixes in Hanami contexts.
Frequently Asked Questions
Can Hanami’s built-in security features prevent container escape?
Does middleBrick scan for container escape vulnerabilities in Ruby/Hanami apps?
/etc/passwd via ../../../host/etc/passwd, middleBrick flags it as a high-severity data exposure finding with remediation guidance.