Aug 20, 2026·7 min read·16 visits
moby/buildkit prior to version 0.31.1 does not enforce size limits or validate file types when reading user and group databases inside build contexts, enabling attackers to crash the buildkitd daemon via memory exhaustion (OOM) or hang execution threads.
moby/buildkit is susceptible to a denial-of-service vulnerability prior to version 0.31.1. When BuildKit processes user or group directives from untrusted build contexts or base images, it reads configuration databases such as /etc/passwd and /etc/group directly into memory without enforcing boundaries. An attacker can exploit this behavior by engineering malicious files that trigger host memory exhaustion or block daemon threads indefinitely.
BuildKit is the primary backend compilation engine for modern container ecosystems, translating declarative source files (such as Dockerfiles) into Low-Level Builder (LLB) Directed Acyclic Graphs (DAGs). This execution framework operates as a high-performance daemon (buildkitd) coordinating with various frontend interfaces. During intermediate compilation stages, BuildKit frequently switches process context ownership or checks system permissions. This requires translating symbolic user and group identifiers defined in instructions like USER, COPY --chown, or RUN --mount=type=bind into numeric execution parameters.
To perform translation without executing full operating system commands inside the target runtime environment, BuildKit parses the target container's localized database files, specifically /etc/passwd and /etc/group. These files reside inside the root filesystem (rootfs) configuration path of the target image state. The attack surface exists because these files are inherently user-controlled, extracted from base images that may be obtained from untrusted or public container registries.
The vulnerability is classified under CWE-770 (Allocation of Resources Without Limits or Throttling). It represents a critical architectural gap where unvalidated, external inputs directly dictate the magnitude of resource allocations within the privileged host service environment.
The vulnerability lies within the identity resolution code paths located in executor/oci/user.go and solver/llbsolver/ops/user_linux.go. When processing instructions requiring user or group translation, the daemon resolves the target file path via fs.RootPath(root, p) to guarantee that path resolution remains jailed within the container's virtual root directory. It then attempts to open the file descriptor using a standard os.Open call.
In vulnerable versions, the application immediately reads and processes the entire contents of these files into heap memory. This open-and-read sequence lacked any size constraints or metadata validation. If the target file size is expanded to several gigabytes, the Go runtime allocates dynamic slice buffers to hold the read contents. Because the Go runtime heap allocator increases buffer capacities exponentially when growing slices, memory consumption quickly balloons, triggering the Linux host's Out-Of-Memory (OOM) killer to terminate the parent buildkitd daemon.
In addition to memory exhaustion, the original implementation failed to inspect the file mode mask returned by the file status system call. If an attacker configured /etc/passwd or /etc/group as a named pipe (FIFO) or a blocking character device, the Go synchronous file read call blocked indefinitely waiting for data. This behavior effectively starves the internal worker pool of active threads, resulting in a thread-leak denial-of-service condition where the build process hangs without recovering.
An analysis of the fix implemented across the vulnerable modules highlights how the boundary enforcement was engineered. The patch introduces a rigid upper boundary (maxUserFileBytes = 10 << 20, or 10 MiB) and adds explicit verification of the file mode using f.Stat().
Below is the technical diff showing the integration of the size constraints and type validation within executor/oci/user.go:
// Patched implementation in executor/oci/user.go
const maxUserFileBytes = 10 << 20
func openUserFile(root, p string) (io.ReadCloser, error) {
p, err := fs.RootPath(root, p)
if err != nil {
return nil, errors.WithStack(err)
}
f, err := os.Open(p)
if err != nil {
return nil, errors.WithStack(err)
}
// Verify file properties prior to allocating parsing buffers
info, err := f.Stat()
if err != nil {
f.Close()
return nil, errors.WithStack(err)
}
if !info.Mode().IsRegular() {
f.Close()
return nil, errors.Errorf("%s is not a regular file", p)
}
// Restrict stream consumer read capacities
return &limitedReadCloser{
ReadCloser: f,
r: &io.LimitedReader{R: f, N: maxUserFileBytes + 1},
name: p,
}, nil
}The wrapper structure limitedReadCloser implements the custom read control. If the underlying io.LimitedReader counts down to zero, meaning the file size exceeds the 10 MiB threshold, the routine immediately returns an error, halting further parsing and releasing the associated memory allocations.
type limitedReadCloser struct {
io.ReadCloser
r *io.LimitedReader
name string
}
func (l *limitedReadCloser) Read(p []byte) (int, error) {
n, err := l.r.Read(p)
if l.r.N == 0 {
return n, errors.Errorf("%q exceeds %d bytes", l.name, maxUserFileBytes)
}
return n, err
}This defensive design is highly effective. The use of fs.RootPath prevents symlink-based container breakouts, and the combination of IsRegular() checks and io.LimitedReader prevents resource exhaustion.
To exploit this vulnerability, an attacker must introduce a malformed base image or a malicious local directory context into the BuildKit pipeline. This is typically achieved in environments that allow arbitrary Dockerfile execution, such as multi-tenant CI/CD platforms.
To construct a memory-exhaustion payload, an attacker can create a sparse file of 15 Gigabytes directly within the /etc/passwd path of a custom base image. Because sparse files do not consume significant storage when compressed, they can easily be pushed to registries like Docker Hub. When BuildKit attempts to read the file, the uncompressed data expands fully in RAM, crashing the host daemon.
Alternatively, to trigger a thread-exhaustion hang, the attacker can replace the /etc/passwd file in their image with a named pipe (FIFO) created via mkfifo rootfs/etc/passwd. When BuildKit initiates a build and encounters a USER directive, it calls os.Open on the named pipe and blocks, consuming system resources until the thread limit is reached.
The overall impact of CVE-2026-61712 is categorized as Low by the CVSS system (Base Score 2.3), reflecting specific limitations on attack vector requirements. Specifically, the vulnerability requires user interaction because an operator or pipeline runner must initiate a container build using the malicious Dockerfile or base image.
However, in enterprise environments, the operational impact of a BuildKit crash can be severe. In shared or multi-tenant CI/CD platforms (such as Kubernetes-based runners using Tekton, Argo Workflows, or GitLab CI), a single malicious build step can terminate the shared buildkitd instance. This termination immediately disrupts all other parallel builds running on the same host, resulting in pipeline failures and cache corruption.
Since no unauthorized file write or data access occurs, Confidentiality and Integrity are unaffected. The primary impact is localized availability degradation, which can be mitigated if automatic process managers (like systemd) restart the daemon immediately, though concurrent active builds must still be rescheduled and restarted from scratch.
The permanent fix for this vulnerability is to upgrade BuildKit to version 0.31.1 or later. If immediate upgrades are not feasible, administrators can apply several configuration mitigations to reduce the risk of exploitation:
buildkitd process under systemd slice configurations or cgroup directives that enforce physical memory limitations (e.g., MemoryMax=4G). This isolates memory exhaustion crashes and prevents host-level instability.[Service]
Restart=always
RestartSec=5sbuildkitd in rootless mode limits its access to host resources and adds layer of isolation between the build runner and the host operating system.CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
buildkit moby | < 0.31.1 | 0.31.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-770 |
| Attack Vector | Network |
| CVSS v4.0 | 2.3 (Low) |
| Impact | Denial of Service (DoS) |
| Exploit Status | none |
| CISA KEV Status | No |
The software allocates memory or other system resources on behalf of an untrusted actor without placing an upper bound on the amount of resources that can be requested, leading to exhaustion of host resources.
An LDAP injection vulnerability exists in the centraldogma-server-auth-shiro module of LY Corporation Central Dogma before version 0.84.0. The search logic dynamically constructs LDAP search filters by interpolating user-provided usernames without escaping RFC 4515 metacharacters. Unauthenticated remote attackers can leverage this flaw to bypass authentication, enumerate directory hierarchies, and access unauthorized resources.
CVE-2026-11746 is a critical vulnerability in Central Dogma Server prior to version 0.84.0, where an embedded ZooKeeper replication secret silently falls back to a publicly known, hard-coded default string ('ch4n63m3'). Remote attackers with access to the replication network can authenticate as legitimate cluster peers, potentially leading to unauthorized data exposure, state manipulation, or complete cluster takeover.
A logical verification flaw in ZITADEL's external JWT Identity Provider validation allows attackers to bypass session expiration checks. If an incoming JWT lacks the 'exp' claim, the system skips validation entirely, creating an indefinitely valid session. This issue has been addressed in versions 3.4.12 and 4.15.2.
CVE-2026-59149 identifies a directory traversal vulnerability in `@mockoon/commons-server`, the backend mock-server library powering the Mockoon application. The flaw occurs in the path containment validation logic used during raw file response generation. An unauthenticated attacker can exploit this weakness to retrieve arbitrary files from sibling directories sharing a common prefix with the designated static base directory.
An in-depth analysis of CVE-2026-59148, a high-severity flaw in Mockoon where unauthenticated administrative endpoints and a wildcard Cross-Origin Resource Sharing (CORS) policy allow remote execution, state poisoning, and credential theft.
An improper authentication vulnerability (CWE-287) in ZITADEL's external identity provider handler before version 4.15.3 allows remote attackers to perform complete account takeover. When auto-linking by email is enabled, ZITADEL verifies that the local target account has a verified email address but fails to verify if the external provider confirmed ownership of that same email. Attackers can exploit this by registering an unverified account with a victim's email address on a permissive external provider, leading to unauthorized account binding and persistent access.