I run a homelab on Proxmox. When I came across OpenClaw — an automated LXC setup script for a browser automation gateway — I wanted to get it running quickly. I pulled the script, ran it, and had a working container in minutes. Convenient. Also a security disaster waiting to happen.

What OpenClaw Is#

OpenClaw is an open-source project that deploys a containerised browser gateway with VNC access inside a Proxmox LXC container. The idea is solid: isolated browser sessions, easy automation, clean separation from the host. The execution, however, had serious problems out of the box.

What Was Wrong#

The original setup script created a privileged LXC container. In Proxmox terms, that means --unprivileged 0. This is the default “easy” mode that many tutorials and quick-start scripts use — and it is genuinely dangerous.

In a privileged container:

  • Root inside the container is root on the Proxmox host. There is no user namespace separation. If an attacker escapes the container (container escapes are a known class of vulnerability), they land directly as root on your hypervisor.
  • All services ran as root. The VNC server, the gateway process, the desktop session — everything ran under the root account. No isolation, no principle of least privilege.
  • brewuser had unrestricted sudo. Any process running as brewuser could run anything as root, no questions asked.
  • Config and data lived under /root. The most privileged path on the system.

This is the kind of configuration that is fine for a two-minute demo and catastrophic in any environment connected to a network.

Analysing It with Claude#

Rather than manually auditing every line of the shell script, I fed it to Claude and asked for a security review. The analysis confirmed the issues above and surfaced a few additional concerns around service dependency ordering and environment variable leakage. Having an AI do the first pass is not a replacement for understanding what you’re running — but it dramatically accelerates the review and catches things you might skim past when you’re in “get it working” mode.

The key insight: treating a public shell script as trusted just because it’s open source is a mistake. Open source means you can audit it. It does not mean someone already has.

What I Fixed#

I submitted the security hardening as PR #2 on the Openclaw-Proxmox repository. The changes:

1. Unprivileged container#

# Before
pct create $CTID ... --unprivileged 0

# After
pct create $CTID ... --unprivileged 1 --features nesting=1

With --unprivileged 1, Proxmox maps container UIDs to a high, non-privileged range on the host via user namespaces. Root inside the container is nobody on the host. This is the single most impactful change.

nesting=1 is required for systemd and dbus to function correctly inside an unprivileged LXC — without it, service management breaks.

2. Dedicated non-root user#

All OpenClaw services (gateway, VNC, desktop) now run under a dedicated openclaw user created during setup. The brewuser sudo permission was scoped down from unrestricted to only the brew binary. The openclaw user is limited to apt-get, service, and systemctl — nothing more.

3. Correct service configuration#

The systemd unit for the gateway now declares Wants=vncserver.service so startup ordering is explicit. Environment variables (DISPLAY, HOME) are set correctly in the unit file rather than relying on inherited root environment. Config and data directories moved from /root to /home/openclaw.

4. Browser sandbox flag#

LXC containers do not have the kernel namespaces that Chrome’s sandbox requires. Added automatic browser.noSandbox=true to the browser config. Without this, Chromium-based browsers simply fail to start inside the container.

Why This Matters#

Container escapes are not theoretical. CVE-2019-5736 (runc), CVE-2022-0185 (Linux kernel), and others have demonstrated that the boundary between container and host can be broken. The question is what an attacker finds when they land on the host side.

With a privileged container: they find root. Game over — full hypervisor compromise, access to all other VMs and containers, potentially the entire network.

With an unprivileged container and a minimal-permission service user: they find a mapped UID with no host privileges, a user that cannot run arbitrary commands, and a container boundary that is significantly harder to cross meaningfully.

The attack surface reduction from privileged → unprivileged, combined with proper service user isolation, is not a minor hardening tweak. It is the difference between a compromised container and a compromised hypervisor.

The General Principle#

Everything freely available from the internet — shell scripts, Helm charts, Ansible roles, Docker Compose files, Terraform modules — should be treated as untrusted input until reviewed. The open-source ecosystem is large, the incentive to audit random scripts is low, and mistakes made by well-meaning authors get copied everywhere.

Before running any infrastructure script in your environment:

  1. Read it. All of it.
  2. If it is long, use an AI assistant for a first-pass security review.
  3. Check what privileges it requests and why.
  4. Check what it runs as root and whether that is actually necessary.
  5. Check whether it phones home, downloads additional scripts at runtime, or modifies system-wide configuration.

This is not paranoia. It is basic operational hygiene that separates engineers who understand their infrastructure from engineers who have infrastructure running them.

Conclusion#

OpenClaw is a useful project. The original setup script was insecure by default — privileged containers, root-running services, unrestricted sudo. A Claude-assisted audit identified the issues quickly, and the hardened version in PR #2 addresses them properly.

The broader lesson: convenience and security are in constant tension in infrastructure tooling. Quick-start scripts optimise for the former. Your job as a senior engineer is to notice that tension, understand the trade-offs, and make the right call before something goes wrong — not after.

The hardened version of the setup script is available in my fork at github.com/koss822/Openclaw-Proxmox.