Container Escape in Hapi (Javascript)
Container Escape in Hapi with Javascript
Hapi is a Node.js framework that provides a structured way to build APIs. When used in containerized environments, specific misconfigurations or unsafe practices can allow attackers to escape the container boundary through the API layer. This typically occurs when Hapi applications expose administrative endpoints, serve static files without proper restrictions, or use unsafe child process handling that can be manipulated via API inputs.
In particular, certain versions of Hapi (prior to 20.0.0) allowed the inject method to execute arbitrary system commands when combined with specific route handlers and environment configurations. If an attacker can control input passed to a route that triggers a shell command, and the container runs with elevated privileges or mounts the host filesystem, it may be possible to break out of the container and interact with the host system.
Such an escape often relies on poor input validation in JavaScript code that directly interpolates user data into child_process.exec or similar APIs. For example, an endpoint that processes file uploads might use the filename parameter in a shell command without sanitization. If the application runs inside a container but shares resources with the host (e.g., via bind mounts), and the Node.js process has sufficient permissions, this could lead to unauthorized file access or command execution on the host.
This type of container escape is not inherent to Hapi itself but arises from how developers configure and deploy it. The risk is highest when Hapi services are deployed with overly permissive Docker settings, such as running as root, enabling host networking, or exposing sensitive host paths.
Mitigations focus on reducing attack surface: running containers with non-root users, avoiding bind mounts of sensitive host directories, and ensuring all user-controlled inputs are strictly validated before use in system calls. Regular dependency updates and using minimal base images (e.g., node:alpine) further reduce exposure.
Javascript-Specific Remediation in Hapi
To prevent container escape via unsafe command execution in Hapi, developers should avoid using child_process.exec or spawnSync with unsanitized user input. Instead, use safer alternatives or ensure strict input validation.
Here is a correct example of a vulnerable route that could lead to command injection:
// Vulnerable code - DO NOT USE in production without validationconst Hapi = require('@hapi/hapi');
const init = async () => {
const server = Hapi.server({ port: 3000 });
server.route({
method: 'POST',
path: '/render',
handler: (request, h) => {
const { filename } = request.payload;
// INSECURE: Directly using user input in shell command
const { exec } = require('child_process');
exec(`convert ${filename} /output/result.png`);
return 'Render started';
}
});
await server.start();
};
init();