Container Escape in Hanami with Cockroachdb
Container Escape in Hanami with Cockroachdb — how this specific combination creates or exposes the vulnerability
A container escape in a Hanami application using CockroachDB can occur when the application or its dependencies expose host-level functionality that an attacker can leverage to break out of the container sandbox. Hanami, being a Ruby web framework, typically runs inside a container with restricted capabilities; however, if the app or its dependencies execute shell commands that interact with the container runtime or node kernel, and those commands include values derived from user input, the attack surface expands.
CockroachDB, as a distributed SQL database, is often accessed via its native PostgreSQL wire protocol. In Hanami, developers commonly use pg or an ORM layer to communicate with CockroachDB. If the application constructs database queries by interpolating user-controlled data into system commands—such as using system, %x, or backticks with unchecked input—an attacker may inject shell metacharacters to execute arbitrary host commands. This can allow reading sensitive files from the host (e.g., /etc/hosts), accessing other containers’ mounted volumes, or invoking the container runtime binary (e.g., docker or ctr) if it is present in the container’s filesystem.
Another vector involves insecure volume mounts. If a Hanami container mounts host paths writable by the application process (e.g., /data), and the application writes executable scripts that are later invoked via system commands, an attacker who compromises the app can replace those scripts to achieve host execution. CockroachDB’s presence does not directly cause the escape, but its common deployment pattern—persistent volumes and network exposure—can encourage configurations where the database service and the application share elevated mount points or environment trust boundaries.
Additionally, if the Hanami app runs with elevated Linux capabilities (e.g., CAP_SYS_ADMIN) to perform operations like mounting filesystems, and those capabilities are not dropped, an attacker can leverage a compromised process to execute container escape techniques such as creating new namespaces or manipulating cgroups. This is especially risky when combined with known kernel exploits or misconfigured seccomp profiles that do not block dangerous syscalls.
middleBrick scans such unauthenticated attack surfaces and flags risky command execution patterns and overly permissive container configurations among its 12 security checks, helping teams detect exposure before an escape is attempted.
Cockroachdb-Specific Remediation in Hanami — concrete code fixes
Remediation focuses on preventing command injection, restricting capabilities, and ensuring safe interaction with CockroachDB. Below are concrete fixes for Hanami apps using CockroachDB.
- Use parameterized queries instead of shell command construction. Replace command interpolation with a safe database client call:
# Unsafe pattern to avoid
user_supplied_id = params[:id]
system("cockroach sql --execute=SELECT * FROM users WHERE id = #{user_supplied_id}")
# Safe pattern using the 'pg' gem directly
require 'pg'
conn = PG.connect(dbname: 'mydb', host: 'cockroachdb.example.com', port: 26257)
result = conn.exec_params('SELECT * FROM users WHERE id = $1', [params[:id]])
- Drop Linux capabilities in the container runtime and avoid mounting host binaries. In your Dockerfile, ensure the process runs as a non-root user and drops unnecessary caps:
# Dockerfile snippet
FROM ruby:3.2-slim
RUN useradd -m appuser
USER appuser
# Ensure dangerous binaries are not accessible
RUN rm -f /usr/bin/docker /usr/bin/ctr || true
- Validate and sanitize all inputs that may reach system commands. If system commands are unavoidable, use
Shellwordsto escape arguments:
require 'shellwords'
user_input = params[:filename]
safe_command = ["cat", Shellwords.escape(user_input)]
system(*safe_command) # safer, but avoid if possible
- Restrict volume mounts to read-only where possible and avoid host path mounts that are writable by the app. In your container orchestrator, define volumes as read-only unless write access is strictly necessary:
# Example docker-compose snippet
services:
hanami_app:
image: my-hanami-app
volumes:
- cockroach-data:/var/lib/cockroach:ro
volumes:
cockroach-data:
By applying these CockroachDB-specific hardening steps within the Hanami application and its container configuration, you reduce the likelihood of container escape and limit the impact of any potential compromise.