Container Escape in Hapi with Mutual Tls
Container Escape in Hapi with Mutual Tls
A container escape in a Hapi service that also enforces Mutual TLS occurs when an attacker who has compromised the application inside the container can leverage the TLS configuration or related trust boundaries to reach the host or other containers. Mutual TLS (mTLS) ensures both client and server present certificates, but it does not reduce the container’s own exploit surface. If the Hapi process runs with elevated privileges or has access to the host’s Unix socket, an attacker who breaches the app can pivot through misconfigured mTLS trust chains or by abusing exposed admin endpoints to escape the container.
Consider a Hapi server that authenticates clients via mTLS using a CA certificate. An insecure default in the TLS library or a runtime with a shared network namespace can allow a compromised container to connect to the host’s Docker API over the mounted socket (e.g., /var/run/docker.sock). This typically stems from runtime misconfiguration rather than the mTLS handshake itself, but mTLS can give a false sense of isolation if operators assume encrypted transport equals container isolation. For example, if the Hapi app is granted access to the Docker socket for logging or orchestration, an authenticated request (even with a valid client cert) could be crafted to abuse exposed endpoints if the Hapi service has a path like /admin/containers that forwards requests without strict authorization checks.
Another scenario involves sidecar or shared-volume attacks. If the Hapi container mounts sensitive host paths (e.g., /etc or /var/lib/docker) and the application is vulnerable to path traversal or deserialization issues, an attacker can read or write files that affect the host or adjacent containers. Mutual TLS protects the API channel but does nothing to prevent file-system abuse originating from within the container. Additionally, if the Hapi server uses environment variables for mTLS credentials that are injected via shared environment namespaces across containers, an attacker who compromises one container can read those variables and use them to authenticate to other services.
To detect such risks, middleBrick scans the unauthenticated attack surface of your Hapi endpoint, including TLS-enabled routes, and can surface findings related to exposed administrative interfaces, overly permissive CORS, and insecure runtime permissions that may facilitate lateral movement or container escape. Note that middleBrick reports findings and provides remediation guidance; it does not fix or block behavior directly.
Mutual Tls-Specific Remediation in Hapi
Remediation centers on tightening runtime permissions, isolating the container, and hardening the mTLS setup in Hapi so that even if the application is compromised, the blast radius is limited. Below are concrete code examples for a Hapi server with mTLS configured securely.
1. Minimalist runtime and non-root execution
Run the container as a non-root user and use a minimal base image. In your Dockerfile:
FROM node:20-alpine
RUN adduser --disabled-password --gecos '' myuser
WORKDIR /app
COPY --chown=myuser:myuser . .
USER myuser
EXPOSE 8080
CMD ["node", "server.js"]
2. Hapi mTLS server setup with strict CA and revocation
This example configures Hapi with mTLS, requiring client certificates signed by a specific CA, and enabling revocation checks. It avoids insecure defaults and does not fall back to unencrypted HTTP.
const Hapi = require('@hapi/hapi');
const tls = require('@hapi/hapi/lib/tls');
const init = async () => {
const server = Hapi.server({
port: 8080,
host: '0.0.0.0',
tls: {
cert: '/run/secrets/server.crt',
key: '/run/secrets/server.key',
ca: ['/run/secrets/ca.crt'],
requestCert: true,
rejectUnauthorized: true,
// Prefer secure TLS settings; avoid older protocols and weak ciphers
minVersion: 'TLSv1.3',
maxVersion: 'TLSv1.3',
ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256'
}
});
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
// client.cert is available because requestCert is true
const cert = request.info.cert;
return { message: 'mTLS secured', subject: cert.subject.name };
}
});
await server.start();
console.log('Server running with mTLS');
};
process.on('unhandledRejection', (err) => {
console.error(err);
process.exit(1);
});
3. Avoid shared Docker socket and restrict capabilities
Do not mount the Docker socket into the container unless absolutely necessary. If you must, enforce strict authorization in Hapi and avoid forwarding raw requests to the socket. Use Docker credentials with least privilege and avoid running the Hapi process with CAP_SYS_ADMIN.
4. Validate and sanitize inputs even with mTLS
Mutual TLS authenticates the client but does not sanitize payloads. Validate all inputs and avoid reflecting raw headers into responses. Use Hapi’s validation features:
server.route({
method: 'POST',
path: '/resource',
options: {
validate: {
headers: Joi.object({
'x-api-key': Joi.string().required()
}),
payload: Joi.object({
name: Joi.string().max(50).required()
})
}
},
handler: (request, h) => { /* safe handling */ }
});
5. Environment isolation and secret management
Do not share environment namespaces across containers for TLS credentials. Use per-container secrets and rotate keys regularly. In Kubernetes, prefer secrets mounted as files rather than env vars when possible to reduce accidental exposure via logs or error traces.
middleBrick can scan your Hapi endpoint to surface findings related to exposed admin routes, CORS misconfigurations, and insecure runtime settings that could aid container escape. Its LLM/AI Security checks also probe for prompt injection risks if your Hapi service exposes AI-related endpoints.