How to Escape from a Container

Learn how ShellHub facilitates installation through containers in this technical article. Discover how a secure bridge is created to run processes on the host from a container, ensuring security and transparency in the process. Additionally, learn more about Q2BSTUDIO and its services e

sábado, 16 de agosto de 2025 • 6 min read • Q2BSTUDIO Team

Artificial-Intelligence-

When I started designing ShellHub, one of the main goals was to make installation easy. I wanted users to be able to try and use the product with minimal friction and barriers. Although users were developers, I thought that the simpler the start, the higher the likelihood that someone would try the project. Looking back, I believe this simplicity was one of the reasons for its success.

From the beginning, it was clear that distributing ShellHub in containers would simplify things a lot. Today, practically any developer has Docker installed on their machine or on servers, and that decision made deployment and initial testing easier.

The decision brought an interesting Linux engineering challenge: how to offer a shell that acts directly on the host operating system when the agent runs inside an isolated container.

The solution was to build a secure bridge that allows starting a process from the container, with that process running in the host context. This is not about exploiting security flaws but about combining Docker tools and Linux kernel features within the rules of the system.

In what follows, I describe the foundation of the bridge and the way to cross from the container to the host.

Summarized general flow: the user connects to the agent inside the container, the agent identifies the user and builds a command that uses nsenter to enter the namespaces of the host's PID 1 and setpriv to adjust UID and GID before launching the real shell on the system.

Part 1: The foundation. Preparing the container with Docker. It all starts with docker run and a series of flags that give the container the visibility and permissions needed to interact with the host.

Essential flags: --privileged grants elevated permissions to the container, allowing access to devices, use of setuid, and other operations that a standard container cannot perform; --pid=host makes the container share the process space with the host, so it can see real processes including PID 1; --network=host places the container on the host's network stack, avoiding port mappings and facilitating communications.

Critical volumes: mounting the host filesystem at a path in the container, for example -v /:/host, allows the agent to read the real filesystem; mounting /etc/passwd, /etc/group, and /etc/shadow in read-only mode allows identifying host users and groups to correctly switch identities.

With these elements, the container has access to the host filesystem, process visibility, shared network, and sufficient permissions to start commands in the host context. The foundation of the bridge is built.

Part 2: The crossing. How to safely exit the container. With guaranteed access to the host, the next step is to start a process that actually runs on the real system even though it is initiated from the container.

Main tool: nsenter. This utility allows entering the namespaces of another process, and since the container shares PID with the host, it can target the host's PID 1, usually systemd or init. With nsenter, you access mount, uts, ipc, net, and pid namespaces, allowing the process to act as if it were on the host.

Security control: setpriv. A process born from nsenter would be running as root because it was started from a privileged container. To prevent the session from having undue privileges, setpriv is used to change real and effective UID and GID and to clear supplementary groups before executing the shell. Important setpriv flags are --reuid, --regid, and --clear-groups, which allow adjusting identity and reducing capabilities.

Example command that assembles the solution: nsenter --target 1 --mount --uts --ipc --net --pid -- setpriv --reuid 1001 --regid 1001 --clear-groups -- /bin/bash --login. This command enters the host context, adjusts the process identity, and starts a clean login shell with the real user's permissions.

Security aspects that this approach mitigates. It avoids unnecessary layers of abstraction by giving direct access to what the user needs, but in a controlled way. It reduces the risk of privilege escalation because setpriv ensures that the final shell does not inherit root privileges. It avoids context confusion by transparently operating in the host namespaces.

Why setpriv is crucial. Without setpriv, the process would have root permissions, which is a serious security problem. setpriv acts as a safety valve to remove unnecessary capabilities, set UID and GID, clear groups, and ensure that the child process cannot regain privileges.

Limitations and precautions. Using --privileged is necessary but carries responsibilities; the agent must be reliable and audited since it has full access to the host. The attack surface increases if the agent code is complex; therefore, it is advisable to keep it small and reviewable. Additionally, the solution depends on Linux kernel features such as namespaces and nsenter, and it is not directly applicable on systems like FreeBSD.

Complete flow in practice when a user connects: the agent inside the container receives the SSH connection, identifies the user by querying the host files, dynamically builds the nsenter plus setpriv command with the user's UID, GID, and shell, executes the command that creates a process in the host context with the correct identity, and connects the process's stdin, stdout, and stderr to the SSH session, providing a transparent experience.

Engineering lessons. Considering simplicity as a non-functional requirement forces creative solutions. Technological limitations can stimulate more elegant solutions. Don't reinvent the wheel; combining existing tools like nsenter and setpriv solves complex problems with little code. Including security from the design stage avoids redoing efforts later.

Conclusion: The choice of Docker to facilitate installation posed a technical challenge that was solved by combining tools from the Linux and Docker ecosystem. The solution is robust and secure when applied with due precautions, and it demonstrates how existing pieces can be creatively assembled to solve real problems.

About Q2BSTUDIO: At Q2BSTUDIO, we are a software development company offering custom applications and custom software for businesses of all sizes. We are specialists in artificial intelligence and AI for businesses, and we develop custom AI agents as well as business intelligence solutions and Power BI projects. We also offer cybersecurity services, audits, and infrastructure hardening, as well as AWS and Azure cloud services for deployment and scaling. Our experience includes integrating artificial intelligence solutions to automate processes, improve decision-making, and create secure and scalable digital products.

If you need a custom solution in artificial intelligence, AI agents, Power BI integration, business intelligence projects, security, or AWS and Azure cloud services, at Q2BSTUDIO we can help you design and implement everything from prototypes to production-ready products. Contact us to learn how we can turn your ideas into custom applications and custom software that drive your business.

Keywords for positioning: custom applications, custom software, artificial intelligence, cybersecurity, cloud services, AWS and Azure, business intelligence services, AI for businesses, AI agents, Power BI.

If the description was empty, this article has been created based on How to Escape from a Container and adapted into Spanish, including Q2BSTUDIO's experience and offerings to improve visibility and positioning with the mentioned keywords.

OUR SERVICES

How we can help you

Do you have a project in mind?

Tell us your vision and we'll turn it into a software solution. Whatever the scope, we make your idea real.