BuildKit interactive containers API does not validate entitlements check
Description
BuildKit is a toolkit for converting source code to build artifacts in an efficient, expressive and repeatable manner. In addition to running containers as build steps, BuildKit also provides APIs for running interactive containers based on built images. It was possible to use these APIs to ask BuildKit to run a container with elevated privileges. Normally, running such containers is only allowed if special security.insecure entitlement is enabled both by buildkitd configuration and allowed by the user initializing the build request. The issue has been fixed in v0.12.5 . Avoid using BuildKit frontends from untrusted sources.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
BuildKit interactive container APIs allowed privilege escalation without proper entitlement validation, fixed in v0.12.5.
Vulnerability
BuildKit provides APIs for running interactive containers based on built images. It was possible to use these APIs to request a container with elevated privileges without the required security.insecure entitlement. Normally, such containers are only allowed if the entitlement is enabled in the buildkitd configuration and authorized by the user initiating the build request. [1][2]
Exploitation
An attacker who can send build requests to a BuildKit daemon can exploit this vulnerability. The issue is in the gateway frontend's execution handling, where privileges are not properly validated against the user's entitlements. The commits show changes to pass the executor with build context and to validate security modes for interactive containers. [3][4]
Impact
A successful exploit could allow an attacker to run a container with elevated privileges, potentially escaping the container sandbox and gaining unauthorized access to the host system. This undermines the security model of BuildKit.
Mitigation
The vulnerability is fixed in BuildKit v0.12.5. Users should update immediately and avoid using BuildKit frontends from untrusted sources.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/moby/buildkitGo | < 0.12.5 | 0.12.5 |
Affected products
141- osv-coords140 versionspkg:apk/chainguard/buildctlpkg:apk/chainguard/buildkitdpkg:apk/chainguard/conftestpkg:apk/chainguard/conftest-fipspkg:apk/chainguard/datadog-agentpkg:apk/chainguard/datadog-agent-core-integrationspkg:apk/chainguard/datadog-agent-core-integrations-fipspkg:apk/chainguard/datadog-agent-fakeintakepkg:apk/chainguard/datadog-agent-fakeintake-fipspkg:apk/chainguard/datadog-agent-fipspkg:apk/chainguard/datadog-agent-jmxpkg:apk/chainguard/datadog-agent-jmx-fipspkg:apk/chainguard/datadog-agent-oci-compatpkg:apk/chainguard/datadog-agent-oci-compat-fipspkg:apk/chainguard/datadog-agent-s6-overlaypkg:apk/chainguard/datadog-agent-s6-overlay-fipspkg:apk/chainguard/datadog-cluster-agentpkg:apk/chainguard/datadog-cluster-agent-fipspkg:apk/chainguard/datadog-cluster-agent-oci-compatpkg:apk/chainguard/datadog-cluster-agent-oci-compat-fipspkg:apk/chainguard/dockerpkg:apk/chainguard/docker-config-mirror-gcrpkg:apk/chainguard/dockerdpkg:apk/chainguard/docker-dindpkg:apk/chainguard/docker-dind-compatpkg:apk/chainguard/dockerd-oci-entrypointpkg:apk/chainguard/dockerd-servicepkg:apk/chainguard/docker-initpkg:apk/chainguard/docker-modprobe-compatpkg:apk/chainguard/docker-oci-entrypointpkg:apk/chainguard/docker-rootlesspkg:apk/chainguard/dogstatsdpkg:apk/chainguard/guacpkg:apk/chainguard/guaccsubpkg:apk/chainguard/guacgqlpkg:apk/chainguard/guacingestpkg:apk/chainguard/guaconepkg:apk/chainguard/kanikopkg:apk/chainguard/kaniko-compatpkg:apk/chainguard/kaniko-warmerpkg:apk/chainguard/kaniko-warmer-compatpkg:apk/chainguard/kubescapepkg:apk/chainguard/scorecardpkg:apk/chainguard/skaffoldpkg:apk/chainguard/trivypkg:apk/chainguard/zotpkg:apk/wolfi/buildctlpkg:apk/wolfi/buildkitdpkg:apk/wolfi/conftestpkg:apk/wolfi/datadog-agentpkg:apk/wolfi/datadog-agent-core-integrationspkg:apk/wolfi/datadog-agent-fakeintakepkg:apk/wolfi/datadog-agent-jmxpkg:apk/wolfi/datadog-agent-oci-compatpkg:apk/wolfi/datadog-agent-s6-overlaypkg:apk/wolfi/datadog-cluster-agentpkg:apk/wolfi/datadog-cluster-agent-oci-compatpkg:apk/wolfi/dockerpkg:apk/wolfi/docker-config-mirror-gcrpkg:apk/wolfi/dockerdpkg:apk/wolfi/docker-dindpkg:apk/wolfi/docker-dind-compatpkg:apk/wolfi/dockerd-oci-entrypointpkg:apk/wolfi/dockerd-servicepkg:apk/wolfi/docker-initpkg:apk/wolfi/docker-modprobe-compatpkg:apk/wolfi/docker-oci-entrypointpkg:apk/wolfi/docker-rootlesspkg:apk/wolfi/dogstatsdpkg:apk/wolfi/guacpkg:apk/wolfi/guaccsubpkg:apk/wolfi/guacgqlpkg:apk/wolfi/guacingestpkg:apk/wolfi/guaconepkg:apk/wolfi/kanikopkg:apk/wolfi/kaniko-compatpkg:apk/wolfi/kaniko-warmerpkg:apk/wolfi/kaniko-warmer-compatpkg:apk/wolfi/kubescapepkg:apk/wolfi/scorecardpkg:apk/wolfi/skaffoldpkg:apk/wolfi/trivypkg:apk/wolfi/zotpkg:golang/github.com/moby/buildkitpkg:rpm/opensuse/buildkit&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/docker&distro=openSUSE%20Leap%2015.5pkg:rpm/opensuse/docker&distro=openSUSE%20Leap%2015.6pkg:rpm/opensuse/docker&distro=openSUSE%20Leap%20Micro%205.3pkg:rpm/opensuse/docker&distro=openSUSE%20Leap%20Micro%205.4pkg:rpm/opensuse/docker&distro=openSUSE%20Leap%20Micro%205.5pkg:rpm/opensuse/docker&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/docker-stable&distro=openSUSE%20Leap%2015.5pkg:rpm/opensuse/docker-stable&distro=openSUSE%20Leap%2015.6pkg:rpm/opensuse/docker-stable&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/singularity-ce&distro=openSUSE%20Tumbleweedpkg:rpm/suse/buildah&distro=SUSE%20Enterprise%20Storage%207.1pkg:rpm/suse/buildah&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP3-LTSSpkg:rpm/suse/buildah&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP3-LTSSpkg:rpm/suse/buildah&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP3pkg:rpm/suse/buildkit&distro=SUSE%20Linux%20Micro%206.0pkg:rpm/suse/docker&distro=SUSE%20Enterprise%20Storage%207.1pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP2-LTSSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP3-LTSSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-ESPOSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-LTSSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Micro%205.1pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Micro%205.2pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Micro%205.3pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Micro%205.4pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Micro%205.5pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2012pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP4pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP5pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP6pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-LTSSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP2-LTSSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP3-LTSSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP4-LTSSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP2pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP3pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP4pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5pkg:rpm/suse/docker&distro=SUSE%20Linux%20Micro%206.0pkg:rpm/suse/docker-stable&distro=SUSE%20Enterprise%20Storage%207.1pkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP3-LTSSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-ESPOSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-LTSSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-ESPOSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-LTSSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP5pkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP6pkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP7pkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-LTSSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP3-LTSSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP4-LTSSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP5-LTSSpkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP3pkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP4pkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP5pkg:rpm/suse/docker-stable&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5
< 0.12.5-r0+ 139 more
- (no CPE)range: < 0.12.5-r0
- (no CPE)range: < 0.12.5-r0
- (no CPE)range: < 0.49.0-r1
- (no CPE)range: < 0.48.0-r2
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 3.0.3-r7
- (no CPE)range: < 4.13.1-r4
- (no CPE)range: < 2.11.0-r0
- (no CPE)range: < 0.49.0-r1
- (no CPE)range: < 2.0.1-r2
- (no CPE)range: < 0.12.5-r0
- (no CPE)range: < 0.12.5-r0
- (no CPE)range: < 0.49.0-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 25.0.2-r0
- (no CPE)range: < 7.50.3-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 0.4.0-r1
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 1.20.1-r0
- (no CPE)range: < 3.0.3-r7
- (no CPE)range: < 4.13.1-r4
- (no CPE)range: < 2.11.0-r0
- (no CPE)range: < 0.49.0-r1
- (no CPE)range: < 2.0.1-r2
- (no CPE)range: < 0.12.5
- (no CPE)range: < 0.12.5-2.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 25.0.6_ce-150000.207.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 25.0.6_ce-150000.207.1
- (no CPE)range: < 24.0.7_ce-3.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-4.1
- (no CPE)range: < 4.1.3-1.1
- (no CPE)range: < 1.35.4-150300.8.25.1
- (no CPE)range: < 1.35.4-150300.8.25.1
- (no CPE)range: < 1.35.4-150300.8.25.1
- (no CPE)range: < 1.35.4-150300.8.25.1
- (no CPE)range: < 0.12.5-1.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-98.106.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 25.0.6_ce-150000.207.1
- (no CPE)range: < 27.5.1_ce-98.126.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 24.0.7_ce-150000.193.1
- (no CPE)range: < 27.5.1_ce-98.126.1
- (no CPE)range: < 25.0.6_ce-1.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.25.1
- (no CPE)range: < 24.0.9_ce-150000.1.25.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.25.1
- (no CPE)range: < 24.0.9_ce-1.20.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.25.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.8.1
- (no CPE)range: < 24.0.9_ce-150000.1.25.1
- (no CPE)range: < 24.0.9_ce-1.20.1
- moby/buildkitv5Range: < 0.12.5
Patches
292cc595cfb12llbsolver: make sure interactive container API validates entitlements
4 files changed · +97 −16
client/build_test.go+51 −7 modified@@ -62,7 +62,8 @@ func TestClientGatewayIntegration(t *testing.T) { ), integration.WithMirroredImages(integration.OfficialImages("busybox:latest"))) integration.Run(t, integration.TestFuncs( - testClientGatewayContainerSecurityMode, + testClientGatewayContainerSecurityModeCaps, + testClientGatewayContainerSecurityModeValidation, ), integration.WithMirroredImages(integration.OfficialImages("busybox:latest")), integration.WithMatrix("secmode", map[string]interface{}{ "sandbox": securitySandbox, @@ -71,7 +72,8 @@ func TestClientGatewayIntegration(t *testing.T) { ) integration.Run(t, integration.TestFuncs( - testClientGatewayContainerHostNetworking, + testClientGatewayContainerHostNetworkingAccess, + testClientGatewayContainerHostNetworkingValidation, ), integration.WithMirroredImages(integration.OfficialImages("busybox:latest")), integration.WithMatrix("netmode", map[string]interface{}{ @@ -1836,9 +1838,17 @@ func testClientGatewayExecFileActionError(t *testing.T, sb integration.Sandbox) checkAllReleasable(t, c, sb, true) } -// testClientGatewayContainerSecurityMode ensures that the correct security mode +// testClientGatewayContainerSecurityModeCaps ensures that the correct security mode // is propagated to the gateway container -func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox) { +func testClientGatewayContainerSecurityModeCaps(t *testing.T, sb integration.Sandbox) { + testClientGatewayContainerSecurityMode(t, sb, false) +} + +func testClientGatewayContainerSecurityModeValidation(t *testing.T, sb integration.Sandbox) { + testClientGatewayContainerSecurityMode(t, sb, true) +} + +func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox, expectFail bool) { integration.CheckFeatureCompat(t, sb, integration.FeatureSecurityMode) requiresLinux(t) @@ -1865,6 +1875,9 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox require.EqualValues(t, 0xa80425fb, caps) } allowedEntitlements = []entitlements.Entitlement{} + if expectFail { + return + } } else { assertCaps = func(caps uint64) { /* @@ -1881,6 +1894,9 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox } mode = llb.SecurityModeInsecure allowedEntitlements = []entitlements.Entitlement{entitlements.EntitlementSecurityInsecure} + if expectFail { + allowedEntitlements = []entitlements.Entitlement{} + } } b := func(ctx context.Context, c client.Client) (*client.Result, error) { @@ -1930,6 +1946,12 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox t.Logf("Stdout: %q", stdout.String()) t.Logf("Stderr: %q", stderr.String()) + if expectFail { + require.Error(t, err) + require.Contains(t, err.Error(), "security.insecure is not allowed") + return nil, err + } + require.NoError(t, err) capsValue, err := strconv.ParseUint(strings.TrimSpace(stdout.String()), 16, 64) @@ -1944,7 +1966,13 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox AllowedEntitlements: allowedEntitlements, } _, err = c.Build(ctx, solveOpts, product, b, nil) - require.NoError(t, err) + + if expectFail { + require.Error(t, err) + require.Contains(t, err.Error(), "security.insecure is not allowed") + } else { + require.NoError(t, err) + } checkAllReleasable(t, c, sb, true) } @@ -2020,7 +2048,15 @@ func testClientGatewayContainerExtraHosts(t *testing.T, sb integration.Sandbox) checkAllReleasable(t, c, sb, true) } -func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandbox) { +func testClientGatewayContainerHostNetworkingAccess(t *testing.T, sb integration.Sandbox) { + testClientGatewayContainerHostNetworking(t, sb, false) +} + +func testClientGatewayContainerHostNetworkingValidation(t *testing.T, sb integration.Sandbox) { + testClientGatewayContainerHostNetworking(t, sb, true) +} + +func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandbox, expectFail bool) { if os.Getenv("BUILDKIT_RUN_NETWORK_INTEGRATION_TESTS") == "" { t.SkipNow() } @@ -2041,6 +2077,9 @@ func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandb if sb.Value("netmode") == hostNetwork { netMode = pb.NetMode_HOST allowedEntitlements = []entitlements.Entitlement{entitlements.EntitlementNetworkHost} + if expectFail { + allowedEntitlements = []entitlements.Entitlement{} + } } c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2099,7 +2138,12 @@ func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandb t.Logf("Stderr: %q", stderr.String()) if netMode == pb.NetMode_HOST { - require.NoError(t, err) + if expectFail { + require.Error(t, err) + require.Contains(t, err.Error(), "network.host is not allowed") + } else { + require.NoError(t, err) + } } else { require.Error(t, err) }
solver/llbsolver/bridge.go+21 −0 modified@@ -25,6 +25,7 @@ import ( "github.com/moby/buildkit/sourcepolicy" spb "github.com/moby/buildkit/sourcepolicy/pb" "github.com/moby/buildkit/util/bklog" + "github.com/moby/buildkit/util/entitlements" "github.com/moby/buildkit/util/flightcontrol" "github.com/moby/buildkit/util/progress" "github.com/moby/buildkit/worker" @@ -165,14 +166,34 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp return res, nil } +func (b *llbBridge) validateEntitlements(p executor.ProcessInfo) error { + ent, err := loadEntitlements(b.builder) + if err != nil { + return err + } + v := entitlements.Values{ + NetworkHost: p.Meta.NetMode == pb.NetMode_HOST, + SecurityInsecure: p.Meta.SecurityMode == pb.SecurityMode_INSECURE, + } + return ent.Check(v) +} + func (b *llbBridge) Run(ctx context.Context, id string, rootfs executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (resourcestypes.Recorder, error) { + if err := b.validateEntitlements(process); err != nil { + return nil, err + } + if err := b.loadExecutor(); err != nil { return nil, err } return b.executor.Run(ctx, id, rootfs, mounts, process, started) } func (b *llbBridge) Exec(ctx context.Context, id string, process executor.ProcessInfo) error { + if err := b.validateEntitlements(process); err != nil { + return err + } + if err := b.loadExecutor(); err != nil { return err }
solver/llbsolver/vertex.go+5 −9 modified@@ -101,16 +101,12 @@ func ValidateEntitlements(ent entitlements.Set) LoadOpt { return func(op *pb.Op, _ *pb.OpMetadata, opt *solver.VertexOptions) error { switch op := op.Op.(type) { case *pb.Op_Exec: - if op.Exec.Network == pb.NetMode_HOST { - if !ent.Allowed(entitlements.EntitlementNetworkHost) { - return errors.Errorf("%s is not allowed", entitlements.EntitlementNetworkHost) - } + v := entitlements.Values{ + NetworkHost: op.Exec.Network == pb.NetMode_HOST, + SecurityInsecure: op.Exec.Security == pb.SecurityMode_INSECURE, } - - if op.Exec.Security == pb.SecurityMode_INSECURE { - if !ent.Allowed(entitlements.EntitlementSecurityInsecure) { - return errors.Errorf("%s is not allowed", entitlements.EntitlementSecurityInsecure) - } + if err := ent.Check(v); err != nil { + return err } } return nil
util/entitlements/entitlements.go+20 −0 modified@@ -58,3 +58,23 @@ func (s Set) Allowed(e Entitlement) bool { _, ok := s[e] return ok } + +func (s Set) Check(v Values) error { + if v.NetworkHost { + if !s.Allowed(EntitlementNetworkHost) { + return errors.Errorf("%s is not allowed", EntitlementNetworkHost) + } + } + + if v.SecurityInsecure { + if !s.Allowed(EntitlementSecurityInsecure) { + return errors.Errorf("%s is not allowed", EntitlementSecurityInsecure) + } + } + return nil +} + +type Values struct { + NetworkHost bool + SecurityInsecure bool +}
5026d95aa333gateway: pass executor with build and not access worker directly
13 files changed · +98 −39
cmd/buildkitd/main.go+2 −2 modified@@ -677,8 +677,8 @@ func newController(c *cli.Context, cfg *config.Config) (*control.Controller, err return nil, err } frontends := map[string]frontend.Frontend{} - frontends["dockerfile.v0"] = forwarder.NewGatewayForwarder(wc, dockerfile.Build) - frontends["gateway.v0"] = gateway.NewGatewayFrontend(wc) + frontends["dockerfile.v0"] = forwarder.NewGatewayForwarder(wc.Infos(), dockerfile.Build) + frontends["gateway.v0"] = gateway.NewGatewayFrontend(wc.Infos()) cacheStorage, err := bboltcachestorage.NewStore(filepath.Join(cfg.Root, "cache.db")) if err != nil {
executor/executor.go+8 −2 modified@@ -6,8 +6,9 @@ import ( "net" "syscall" + "github.com/containerd/containerd/mount" + "github.com/docker/docker/pkg/idtools" resourcestypes "github.com/moby/buildkit/executor/resources/types" - "github.com/moby/buildkit/snapshot" "github.com/moby/buildkit/solver/pb" ) @@ -28,8 +29,13 @@ type Meta struct { RemoveMountStubsRecursive bool } +type MountableRef interface { + Mount() ([]mount.Mount, func() error, error) + IdentityMapping() *idtools.IdentityMapping +} + type Mountable interface { - Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) + Mount(ctx context.Context, readonly bool) (MountableRef, error) } type Mount struct {
frontend/frontend.go+2 −1 modified@@ -4,6 +4,7 @@ import ( "context" "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/executor" gw "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/session" "github.com/moby/buildkit/solver" @@ -17,7 +18,7 @@ type Result = result.Result[solver.ResultProxy] type Attestation = result.Attestation[solver.ResultProxy] type Frontend interface { - Solve(ctx context.Context, llb FrontendLLBBridge, opt map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (*Result, error) + Solve(ctx context.Context, llb FrontendLLBBridge, exec executor.Executor, opt map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (*Result, error) } type FrontendLLBBridge interface {
frontend/gateway/container/container.go+4 −5 modified@@ -47,7 +47,7 @@ type Mount struct { WorkerRef *worker.WorkerRef } -func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g session.Group, req NewContainerRequest) (client.Container, error) { +func NewContainer(ctx context.Context, cm cache.Manager, exec executor.Executor, sm *session.Manager, g session.Group, req NewContainerRequest) (client.Container, error) { ctx, cancel := context.WithCancel(ctx) eg, ctx := errgroup.WithContext(ctx) platform := opspb.Platform{ @@ -63,7 +63,7 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s hostname: req.Hostname, extraHosts: req.ExtraHosts, platform: platform, - executor: w.Executor(), + executor: exec, sm: sm, group: g, errGroup: eg, @@ -86,9 +86,8 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s } name := fmt.Sprintf("container %s", req.ContainerID) - mm := mounts.NewMountManager(name, w.CacheManager(), sm) - p, err := PrepareMounts(ctx, mm, w.CacheManager(), g, "", mnts, refs, func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) { - cm := w.CacheManager() + mm := mounts.NewMountManager(name, cm, sm) + p, err := PrepareMounts(ctx, mm, cm, g, "", mnts, refs, func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) { if m.Input != opspb.Empty { cm = refs[m.Input].Worker.CacheManager() }
frontend/gateway/forwarder/forward.go+6 −3 modified@@ -6,6 +6,7 @@ import ( cacheutil "github.com/moby/buildkit/cache/util" "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/executor" "github.com/moby/buildkit/frontend" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/frontend/gateway/container" @@ -26,7 +27,7 @@ import ( "golang.org/x/sync/errgroup" ) -func LLBBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, w worker.Infos, sid string, sm *session.Manager) (*BridgeClient, error) { +func LLBBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*opspb.Definition, w worker.Infos, sid string, sm *session.Manager) (*BridgeClient, error) { bc := &BridgeClient{ opts: opts, inputs: inputs, @@ -35,6 +36,7 @@ func LLBBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLL sm: sm, workers: w, workerRefByID: make(map[string]*worker.WorkerRef), + executor: exec, } bc.buildOpts = bc.loadBuildOpts() return bc, nil @@ -52,6 +54,7 @@ type BridgeClient struct { workerRefByID map[string]*worker.WorkerRef buildOpts client.BuildOpts ctrs []client.Container + executor executor.Executor } func (c *BridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) { @@ -293,13 +296,13 @@ func (c *BridgeClient) NewContainer(ctx context.Context, req client.NewContainer return nil, err } - w, err := c.workers.GetDefault() + cm, err := c.workers.DefaultCacheManager() if err != nil { return nil, err } group := session.NewGroup(c.sid) - ctr, err := container.NewContainer(ctx, w, c.sm, group, ctrReq) + ctr, err := container.NewContainer(ctx, cm, c.executor, c.sm, group, ctrReq) if err != nil { return nil, err }
frontend/gateway/forwarder/frontend.go+3 −2 modified@@ -3,6 +3,7 @@ package forwarder import ( "context" + "github.com/moby/buildkit/executor" "github.com/moby/buildkit/frontend" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/session" @@ -22,8 +23,8 @@ type GatewayForwarder struct { f client.BuildFunc } -func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (retRes *frontend.Result, retErr error) { - c, err := LLBBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers, sid, sm) +func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (retRes *frontend.Result, retErr error) { + c, err := LLBBridgeToGatewayClient(ctx, llbBridge, exec, opts, inputs, gf.workers, sid, sm) if err != nil { return nil, err }
frontend/gateway/gateway.go+13 −16 modified@@ -86,7 +86,7 @@ func filterPrefix(opts map[string]string, pfx string) map[string]string { return m } -func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*frontend.Result, error) { +func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*frontend.Result, error) { source, ok := opts[keySource] if !ok { return nil, errors.Errorf("no source specified for gateway") @@ -141,7 +141,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten } } } else { - c, err := forwarder.LLBBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers, sid, sm) + c, err := forwarder.LLBBridgeToGatewayClient(ctx, llbBridge, exec, opts, inputs, gf.workers, sid, sm) if err != nil { return nil, err } @@ -281,18 +281,13 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten } } - lbf, ctx, err := serveLLBBridgeForwarder(ctx, llbBridge, gf.workers, inputs, sid, sm) + lbf, ctx, err := serveLLBBridgeForwarder(ctx, llbBridge, exec, gf.workers, inputs, sid, sm) defer lbf.conn.Close() //nolint if err != nil { return nil, err } defer lbf.Discard() - w, err := gf.workers.GetDefault() - if err != nil { - return nil, err - } - mdmnt, release, err := metadataMount(frontendDef) if err != nil { return nil, err @@ -305,7 +300,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten mnts = append(mnts, *mdmnt) } - _, err = w.Executor().Run(ctx, "", container.MountWithSession(rootFS, session.NewGroup(sid)), mnts, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil) + _, err = exec.Run(ctx, "", container.MountWithSession(rootFS, session.NewGroup(sid)), mnts, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil) if err != nil { if errdefs.IsCanceled(ctx, err) && lbf.isErrServerClosed { err = errors.Errorf("frontend grpc server closed unexpectedly") @@ -434,11 +429,11 @@ func (lbf *llbBridgeForwarder) Result() (*frontend.Result, error) { return lbf.result, nil } -func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) LLBBridgeForwarder { - return newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm) +func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) LLBBridgeForwarder { + return newBridgeForwarder(ctx, llbBridge, exec, workers, inputs, sid, sm) } -func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) *llbBridgeForwarder { +func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) *llbBridgeForwarder { lbf := &llbBridgeForwarder{ callCtx: ctx, llbBridge: llbBridge, @@ -451,13 +446,14 @@ func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridg sid: sid, sm: sm, ctrs: map[string]gwclient.Container{}, + executor: exec, } return lbf } -func serveLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*llbBridgeForwarder, context.Context, error) { +func serveLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*llbBridgeForwarder, context.Context, error) { ctx, cancel := context.WithCancel(ctx) - lbf := newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm) + lbf := newBridgeForwarder(ctx, llbBridge, exec, workers, inputs, sid, sm) server := grpc.NewServer(grpc.UnaryInterceptor(grpcerrors.UnaryServerInterceptor), grpc.StreamInterceptor(grpcerrors.StreamServerInterceptor)) grpc_health_v1.RegisterHealthServer(server, health.NewServer()) pb.RegisterLLBBridgeServer(server, lbf) @@ -552,6 +548,7 @@ type llbBridgeForwarder struct { isErrServerClosed bool sid string sm *session.Manager + executor executor.Executor *pipe ctrs map[string]gwclient.Container ctrsMu sync.Mutex @@ -1042,7 +1039,7 @@ func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewConta // and we want the context to live for the duration of the container. group := session.NewGroup(lbf.sid) - w, err := lbf.workers.GetDefault() + cm, err := lbf.workers.DefaultCacheManager() if err != nil { return nil, stack.Enable(err) } @@ -1052,7 +1049,7 @@ func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewConta return nil, stack.Enable(err) } - ctr, err := container.NewContainer(context.Background(), w, lbf.sm, group, ctrReq) + ctr, err := container.NewContainer(context.Background(), cm, lbf.executor, lbf.sm, group, ctrReq) if err != nil { return nil, stack.Enable(err) }
snapshot/snapshotter.go+2 −5 modified@@ -10,14 +10,11 @@ import ( "github.com/containerd/containerd/pkg/userns" "github.com/containerd/containerd/snapshots" "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/executor" "github.com/pkg/errors" ) -type Mountable interface { - // ID() string - Mount() ([]mount.Mount, func() error, error) - IdentityMapping() *idtools.IdentityMapping -} +type Mountable = executor.MountableRef // Snapshotter defines interface that any snapshot implementation should satisfy type Snapshotter interface {
solver/llbsolver/bridge.go+32 −0 modified@@ -11,6 +11,8 @@ import ( "github.com/moby/buildkit/cache/remotecache" "github.com/moby/buildkit/client" "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/executor" + resourcestypes "github.com/moby/buildkit/executor/resources/types" "github.com/moby/buildkit/frontend" gw "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/identity" @@ -39,6 +41,10 @@ type llbBridge struct { cms map[string]solver.CacheManager cmsMu sync.Mutex sm *session.Manager + + executorOnce sync.Once + executorErr error + executor executor.Executor } func (b *llbBridge) Warn(ctx context.Context, dgst digest.Digest, msg string, opts frontend.WarnOpts) error { @@ -159,6 +165,32 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp return res, nil } +func (b *llbBridge) Run(ctx context.Context, id string, rootfs executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (resourcestypes.Recorder, error) { + if err := b.loadExecutor(); err != nil { + return nil, err + } + return b.executor.Run(ctx, id, rootfs, mounts, process, started) +} + +func (b *llbBridge) Exec(ctx context.Context, id string, process executor.ProcessInfo) error { + if err := b.loadExecutor(); err != nil { + return err + } + return b.executor.Exec(ctx, id, process) +} + +func (b *llbBridge) loadExecutor() error { + b.executorOnce.Do(func() { + w, err := b.resolveWorker() + if err != nil { + b.executorErr = err + return + } + b.executor = w.Executor() + }) + return b.executorErr +} + type resultProxy struct { id string b *provenanceBridge
solver/llbsolver/provenance.go+1 −1 modified@@ -165,7 +165,7 @@ func (b *provenanceBridge) Solve(ctx context.Context, req frontend.SolveRequest, return nil, errors.Errorf("invalid frontend: %s", req.Frontend) } wb := &provenanceBridge{llbBridge: b.llbBridge, req: &req} - res, err = f.Solve(ctx, wb, req.FrontendOpt, req.FrontendInputs, sid, b.llbBridge.sm) + res, err = f.Solve(ctx, wb, b.llbBridge, req.FrontendOpt, req.FrontendInputs, sid, b.llbBridge.sm) if err != nil { return nil, err }
solver/llbsolver/solver.go+1 −1 modified@@ -458,7 +458,7 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro br := s.bridge(j) var fwd gateway.LLBBridgeForwarder if s.gatewayForwarder != nil && req.Definition == nil && req.Frontend == "" { - fwd = gateway.NewBridgeForwarder(ctx, br, s.workerController, req.FrontendInputs, sessionID, s.sm) + fwd = gateway.NewBridgeForwarder(ctx, br, br, s.workerController.Infos(), req.FrontendInputs, sessionID, s.sm) defer fwd.Discard() // Register build before calling s.recordBuildHistory, because // s.recordBuildHistory can block for several seconds on
worker/workercontroller.go+23 −0 modified@@ -3,6 +3,7 @@ package worker import ( "github.com/containerd/containerd/filters" "github.com/hashicorp/go-multierror" + "github.com/moby/buildkit/cache" "github.com/moby/buildkit/client" "github.com/pkg/errors" ) @@ -81,3 +82,25 @@ func (c *Controller) WorkerInfos() []client.WorkerInfo { } return out } + +func (c *Controller) Infos() Infos { + return &infosController{c: c} +} + +type infosController struct { + c *Controller +} + +var _ Infos = &infosController{} + +func (c *infosController) DefaultCacheManager() (cache.Manager, error) { + w, err := c.c.GetDefault() + if err != nil { + return nil, err + } + return w.CacheManager(), nil +} + +func (c *infosController) WorkerInfos() []client.WorkerInfo { + return c.c.WorkerInfos() +}
worker/worker.go+1 −1 modified@@ -43,6 +43,6 @@ type Worker interface { } type Infos interface { - GetDefault() (Worker, error) + DefaultCacheManager() (cache.Manager, error) WorkerInfos() []client.WorkerInfo }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-wr6v-9f75-vh2gghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-23653ghsaADVISORY
- github.com/moby/buildkit/commit/5026d95aa3336e97cfe46e3764f52d08bac7a10eghsaWEB
- github.com/moby/buildkit/commit/92cc595cfb12891d4b3ae476e067c74250e4b71eghsaWEB
- github.com/moby/buildkit/pull/4602ghsax_refsource_MISCWEB
- github.com/moby/buildkit/releases/tag/v0.12.5ghsax_refsource_MISCWEB
- github.com/moby/buildkit/security/advisories/GHSA-wr6v-9f75-vh2gghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.