HIGH container escapehanamiruby

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?
Hanami provides secure defaults for common web vulnerabilities (e.g., CSRF, XSS) via its action flow and view escaping, but it does not guard against container escape, which stems from runtime environment and file system access. Prevention requires validating user input in Ruby code (e.g., sanitizing file names) and configuring containers with least privilege — areas where middleBrick provides actionable findings.
Does middleBrick scan for container escape vulnerabilities in Ruby/Hanami apps?
middleBrick does not directly detect container misconfigurations (like privileged flags or volume mounts), but it identifies application-level risks that could lead to escape — such as path traversal, arbitrary file read/write, or information leakage — through unauthenticated API scanning. For example, if a Hanami endpoint exposes /etc/passwd via ../../../host/etc/passwd, middleBrick flags it as a high-severity data exposure finding with remediation guidance.