Container Escape in Hanami
How Container Escape Manifests in Hanami
Container escape in Hanami applications typically occurs when untrusted code gains access to host system resources through improper configuration or vulnerable dependencies. In Hanami's architecture, this can manifest through several specific attack vectors:
# Vulnerable Hanami action allowing path traversal
class Files::Download < Hanami::Action
def handle(req, res)
file_path = req.params[:file]
# No validation of file path - allows escape from container
res.body = File.read(file_path)
end
end
The most common container escape patterns in Hanami involve:
- Unsafe file operations that traverse outside the intended directory
- Mounting host directories with excessive permissions into the container
- Using privileged containers that expose host namespaces
- Vulnerable dependencies that allow command injection
A particularly dangerous pattern appears when Hanami applications mount host volumes:
# docker-compose.yml - problematic configuration
version: '3.8'
services:
hanami_app:
build: .
volumes:
- ./:/app:rw # Read-write access to entire host
- /:/host:rw # Direct access to host filesystem
This configuration allows a compromised Hanami application to modify files outside the container, access sensitive host data, or modify container orchestration files.
Hanami-Specific Detection
Detecting container escape vulnerabilities in Hanami requires examining both code patterns and runtime configurations. Key detection methods include:
# Check for vulnerable file operations in Hanami actions
grep -r 'File\|Dir\|IO' apps/ | grep -E '(params|query)'
middleBrick's scanner specifically identifies container escape risks in Hanami applications by testing:
- Authentication bypass attempts that could lead to unauthorized file access
- Path traversal payloads against file handling endpoints
- Unsafe consumption of external data sources
For Hanami applications, middleBrick tests these specific endpoints:
# Example endpoint vulnerable to path traversal
module API::V1::Controllers
class Files < Hanami::Action
def handle(req, res)
path = req.params[:path]
# No sanitization - allows ../ traversal
res.body = File.read("/data/files/#{path}")
end
end
end
The scanner also checks for improper container configurations:
# Dockerfile - checking for privileged flags
FROM ruby:3.1
# Privileged containers allow namespace escape
USER root
# Missing security contexts
middleBrick's LLM security checks are particularly relevant for Hanami applications using AI features, as LLM endpoints can be abused for data exfiltration if not properly secured.
Hanami-Specific Remediation
Securing Hanami applications against container escape requires both code hardening and proper container configuration. Here are Hanami-specific remediation patterns:
# Secure file download action with path validation
class Files::Download < Hanami::Action
def handle(req, res)
requested_file = req.params[:file]
safe_path = validate_file_path(requested_file)
if safe_path
res.body = File.read(safe_path)
else
res.status = 400
res.body = { error: 'Invalid file path' }
end
end
private
def validate_file_path(path)
base_dir = Hanami.root.join('public', 'downloads').to_s
full_path = File.expand_path(path, base_dir)
# Ensure path stays within base directory
return nil unless full_path.start_with?(base_dir)
# Check file exists and is readable
File.exist?(full_path) ? full_path : nil
end
end
For Hanami applications using Docker, implement these security practices:
# Secure Dockerfile for Hanami applications
FROM ruby:3.1-slim
# Create non-root user
RUN addgroup --system hanami && adduser --system --group hanami
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install --without development test
COPY . .
RUN chown -R hanami:hanami /app
USER hanami
# Drop unnecessary capabilities
# Use read-only filesystems where possible
Hanami's configuration system allows additional security controls:
# config/application.rb - security middleware
Hanami.configure do
middleware do
use Rack::Protection::PathTraversal
use Rack::Protection::XSSHeader
use Rack::Protection::ContentSecurityPolicy
end
end
For applications using external services, implement proper network segmentation:
# docker-compose.yml - network isolation
version: '3.8'
services:
hanami_app:
build: .
networks:
- app_network
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
networks:
app_network:
internal: true