Introduction
A single non-recursive read-only remount in Windmill's nsjail sandbox configuration left Kubernetes-injected files writable inside script execution jails. Any authenticated user could then poison DNS resolution persistently and intercept credentials from every tenant sharing the same worker pod. CVE-2026-47107 has a CVSS score of 9.6, and exploiting it takes nothing more than the ability to run a sandboxed script. For multi-tenant Windmill deployments, that is a serious exposure.
Windmill is an open-source developer platform (AGPLv3) that provides infrastructure for internal APIs, background jobs, and workflows. Organizations use it to orchestrate automation pipelines, and it offers multiple layers of process isolation, including nsjail sandboxing, to protect infrastructure from malicious code. Multi-tenant deployments share long-lived worker pods, so any sandbox escape becomes a cross-tenant problem.
Technical Information
Root Cause: Non-Recursive Read-Only Remount
The vulnerability stems from how nsjail applies mount namespace restrictions in Kubernetes environments. Windmill's nsjail configuration files mount the entire /etc directory as read only. That works for ordinary files that exist directly on the filesystem. In Kubernetes, though, the kubelet injects specific files into /etc as separate bind mounts layered on top of the directory. These include /etc/hosts, /etc/resolv.conf, and /etc/hostname.
nsjail applies its read-only remount non-recursively, and the classic mount syscall does not propagate the read-only status to submounts. As a result, the kubelet-injected files remain fully writable inside the jail, even though the parent /etc directory is mounted read only.
Writable Targets
The table below lists the files reported as writable and which source reports each one:
| File Target | Confirmed by Windmill PR #9194 | Cited by VulnCheck Advisory | Notes |
|---|---|---|---|
/etc/hosts | Yes | Yes | Kubelet submount remains writable |
/etc/resolv.conf | Yes | Yes | Kubelet submount remains writable |
/etc/hostname | Yes | No | Kubelet submount remains writable |
/etc/ssl/certs/ca-certificates.crt | No | Yes | Cited in advisory; requires local validation |
Attack Flow
Exploitation proceeds in five steps:
-
Initial access: An authenticated user with permission to execute scripts in any Windmill workspace submits a job that runs inside the nsjail sandbox.
-
File modification: From within the sandbox, the attacker writes malicious entries to the writable files. For example, they can append entries to
/etc/hoststhat redirect legitimate hostnames to attacker-controlled IP addresses, or modify/etc/resolv.confto point DNS resolution at an attacker-controlled resolver. -
Persistence via pod reuse: Windmill worker pods are long-lived and reused across all workspaces and tenants. The poisoned entries persist at the pod level for the lifetime of the worker pod, and every later job executed on that pod inherits the poisoned configuration.
-
Cross-tenant impact: When a victim in a different tenant runs a script on the same worker pod, their job's network traffic follows the attacker's DNS and host redirections. From there the attacker can:
- Redirect hostnames to attacker-controlled servers via
/etc/hosts - Intercept all DNS queries via a rogue resolver in
/etc/resolv.conf - Perform transparent HTTPS man-in-the-middle attacks by injecting a rogue CA certificate, if
/etc/ssl/certs/ca-certificates.crtis also writable - Intercept
WM_TOKENJWTs, which grant workspace admin access to victim workspaces
- Redirect hostnames to attacker-controlled servers via
-
Credential theft and lateral movement: With the intercepted
WM_TOKENJWTs, the attacker gains workspace admin privileges in victim workspaces across tenant boundaries. From there they can exfiltrate more data or mount supply chain attacks by redirecting package registry traffic.
Why This Is Particularly Dangerous
Three factors combine here. The attack needs only low privilege (any authenticated user who can run a script), persistence is automatic because worker pods are reused, and the blast radius covers every tenant on the affected worker. The victim also gets no sign that their DNS resolution has been tampered with.
The Fix in Version 1.703.2
The patch in Pull Request #9194 adds explicit read-only per-file binds for the affected files to all eighteen nsjail configuration files. Each bind shadows a writable kubelet submount with a read-only view of the same content, which closes the gap the non-recursive remount left open.
The fix applies only to the nsjail isolation mode. The "unshare" and "none" isolation modes do not use mount namespaces, and the patch does not cover them:
| Isolation Mode | Mount Namespace Present | Covered by 1.703.2 Fix | Recommendation |
|---|---|---|---|
| nsjail | Yes | Yes | Enforce for all multi-tenant workloads |
| unshare | No | No | Avoid for multi-tenant environments |
| none | No | No | Avoid for multi-tenant environments |
Affected Systems and Versions
All Windmill versions before 1.703.2 are affected when they use the nsjail isolation mode in Kubernetes deployments. The vulnerability requires:
- Windmill versions before 1.703.2
- nsjail isolation mode enabled
- Deployment on Kubernetes (where the kubelet injects bind mounts into
/etc) - Multi-tenant configuration with shared worker pods
Single-tenant deployments, and deployments not running on Kubernetes, may not be affected by the kubelet submount behavior. Validate this independently for your own environment.
Vendor Security History
Windmill has had several notable security issues recently:
| Issue | Identifier | Impact |
|---|---|---|
| Path traversal in log endpoint | GHSA-24fr-44f8-fqwg | Exposure of SUPERADMIN_SECRET leading to potential code execution |
| Slack OAuth secret disclosure | CVE-2026-26964 | Exposure of sensitive OAuth tokens to non-admin users |
| nsjail submount writability | CVE-2026-47107 | Cross-tenant DNS poisoning and token theft |
These issues cluster around access control and isolation boundaries, which organizations that depend on Windmill in security-sensitive contexts should keep in mind. The maintainers have been responsive in addressing reported issues, but the recurrence suggests that isolation and permission boundaries need a more systematic review.
References
- VulnCheck Advisory: Windmill < 1.703.2 Incorrect Default Permissions in nsjail Configuration
- Windmill Pull Request #9194: Fix cross tenant DNS poisoning via writable /etc in nsjail
- Windmill Commit f8467f3
- Windmill Release v1.703.2
- Windmill Security and Process Isolation Documentation
- GHSA-24fr-44f8-fqwg: SUPERADMIN_SECRET Exposure



