BuildKit possible panic when incorrect parameters sent from frontend
Description
BuildKit is a toolkit for converting source code to build artifacts in an efficient, expressive and repeatable manner. A malicious BuildKit client or frontend could craft a request that could lead to BuildKit daemon crashing with a panic. The issue has been fixed in v0.12.5. As a workaround, avoid using BuildKit frontends from untrusted sources.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A malicious BuildKit client or frontend can craft a request causing the daemon to crash with a panic; fixed in v0.12.5.
Vulnerability
Description
CVE-2024-23650 is a denial-of-service vulnerability in BuildKit, a toolkit for converting source code into build artifacts. A malicious BuildKit client or frontend can send a crafted request that triggers a nil pointer dereference in the source policy validation logic, leading to a crash of the BuildKit daemon [1][2]. The root cause is insufficient validation of nil values in source policy rules, as addressed in commit e1924dc [3] and pull request #4601 [4].
Exploitation
The attack can be carried out by an unauthenticated attacker who is able to interact with the BuildKit daemon, either as a client or by providing a malicious frontend. No special privileges are required beyond the ability to send requests to the daemon. The crafted request exploits missing checks for nil selectors or actions within policy rules, causing the daemon to panic when processing the request [3][4].
Impact
Successful exploitation results in a crash of the BuildKit daemon, causing a denial of service. Build processes running on the affected daemon would be terminated, and any pending builds would be lost. The vulnerability does not allow arbitrary code execution or data exfiltration, but it can disrupt build pipelines and automated deployments.
Mitigation
The issue has been fixed in BuildKit version 0.12.5 [2]. Users should upgrade to this version or later. As a workaround, administrators should avoid using BuildKit frontends from untrusted sources and restrict network access to the BuildKit daemon to trusted clients only [1][2].
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
125- osv-coords124 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/docker&distro=openSUSE%20Leap%2015.6pkg: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/docker&distro=SUSE%20Enterprise%20Storage%207.1pkg: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%20High%20Performance%20Computing%2015%20SP5-ESPOSpkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-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%2015%20SP6pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-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%2015%20SP5-LTSSpkg: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%20for%20SAP%20Applications%2015%20SP5pkg:rpm/suse/docker&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5pkg: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%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+ 123 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: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 24.0.9_ce-150000.1.11.1
- (no CPE)range: < 24.0.9_ce-6.1
- (no CPE)range: < 4.1.3-1.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-98.126.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-150000.218.1
- (no CPE)range: < 27.5.1_ce-98.126.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.25.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.25.1
- (no CPE)range: < 24.0.9_ce-150000.1.11.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.25.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.25.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-1.20.1
- moby/buildkitv5Range: < 0.12.5
Patches
57718bd5c3dc8pb: add extra validation to protobuf types
6 files changed · +64 −12
client/validation_test.go+5 −3 modified@@ -17,6 +17,7 @@ import ( func testValidateNullConfig(t *testing.T, sb integration.Sandbox) { requiresLinux(t) + integration.CheckFeatureCompat(t, sb, integration.FeatureOCIExporter) ctx := sb.Context() @@ -55,6 +56,7 @@ func testValidateNullConfig(t *testing.T, sb integration.Sandbox) { func testValidateInvalidConfig(t *testing.T, sb integration.Sandbox) { requiresLinux(t) + integration.CheckFeatureCompat(t, sb, integration.FeatureOCIExporter) ctx := sb.Context() @@ -96,11 +98,12 @@ func testValidateInvalidConfig(t *testing.T, sb integration.Sandbox) { }, }, "", b, nil) require.Error(t, err) - require.Contains(t, err.Error(), "invalid image config for export: missing os") + require.Contains(t, err.Error(), "invalid image config: os and architecture must be specified together") } func testValidatePlatformsEmpty(t *testing.T, sb integration.Sandbox) { requiresLinux(t) + integration.CheckFeatureCompat(t, sb, integration.FeatureOCIExporter) ctx := sb.Context() @@ -139,6 +142,7 @@ func testValidatePlatformsEmpty(t *testing.T, sb integration.Sandbox) { func testValidatePlatformsInvalid(t *testing.T, sb integration.Sandbox) { requiresLinux(t) + integration.CheckFeatureCompat(t, sb, integration.FeatureOCIExporter) ctx := sb.Context() @@ -271,7 +275,6 @@ func testValidateSourcePolicy(t *testing.T, sb integration.Sandbox) { for _, tc := range tcases { t.Run(tc.name, func(t *testing.T) { - var viaFrontend bool b := func(ctx context.Context, c client.Client) (*client.Result, error) { @@ -302,7 +305,6 @@ func testValidateSourcePolicy(t *testing.T, sb integration.Sandbox) { _, err = c.Build(ctx, SolveOpt{}, "", b, nil) require.Error(t, err) require.Contains(t, err.Error(), tc.exp) - }) } }
control/control.go+3 −0 modified@@ -405,6 +405,9 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (* var cacheImports []frontend.CacheOptionsEntry for _, im := range req.Cache.Imports { + if im == nil { + continue + } cacheImports = append(cacheImports, frontend.CacheOptionsEntry{ Type: im.Type, Attrs: im.Attrs,
frontend/gateway/client/attestation.go+6 −0 modified@@ -30,8 +30,14 @@ func AttestationToPB[T any](a *result.Attestation[T]) (*pb.Attestation, error) { } func AttestationFromPB[T any](a *pb.Attestation) (*result.Attestation[T], error) { + if a == nil { + return nil, errors.Errorf("invalid nil attestation") + } subjects := make([]result.InTotoSubject, len(a.InTotoSubjects)) for i, subject := range a.InTotoSubjects { + if subject == nil { + return nil, errors.Errorf("invalid nil attestation subject") + } subjects[i] = result.InTotoSubject{ Kind: subject.Kind, Name: subject.Name,
frontend/gateway/gateway.go+15 −0 modified@@ -646,12 +646,21 @@ func (lbf *llbBridgeForwarder) registerResultIDs(results ...solver.Result) (ids func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest) (*pb.SolveResponse, error) { var cacheImports []frontend.CacheOptionsEntry for _, e := range req.CacheImports { + if e == nil { + return nil, errors.Errorf("invalid nil cache import") + } cacheImports = append(cacheImports, frontend.CacheOptionsEntry{ Type: e.Type, Attrs: e.Attrs, }) } + for _, p := range req.SourcePolicies { + if p == nil { + return nil, errors.Errorf("invalid nil source policy") + } + } + ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx) res, err := lbf.llbBridge.Solve(ctx, frontend.SolveRequest{ Evaluate: req.Evaluate, @@ -1077,6 +1086,12 @@ func (lbf *llbBridgeForwarder) ReleaseContainer(ctx context.Context, in *pb.Rele } func (lbf *llbBridgeForwarder) Warn(ctx context.Context, in *pb.WarnRequest) (*pb.WarnResponse, error) { + // validate ranges are valid + for _, r := range in.Ranges { + if r == nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid source range") + } + } err := lbf.llbBridge.Warn(ctx, in.Digest, string(in.Short), frontend.WarnOpts{ Level: int(in.Level), SourceInfo: in.Info,
util/tracing/transform/attribute.go+16 −5 modified@@ -13,6 +13,9 @@ func Attributes(attrs []*commonpb.KeyValue) []attribute.KeyValue { out := make([]attribute.KeyValue, 0, len(attrs)) for _, a := range attrs { + if a == nil { + continue + } kv := attribute.KeyValue{ Key: attribute.Key(a.Key), Value: toValue(a.Value), @@ -42,37 +45,45 @@ func toValue(v *commonpb.AnyValue) attribute.Value { func boolArray(kv []*commonpb.AnyValue) attribute.Value { arr := make([]bool, len(kv)) for i, v := range kv { - arr[i] = v.GetBoolValue() + if v != nil { + arr[i] = v.GetBoolValue() + } } return attribute.BoolSliceValue(arr) } func intArray(kv []*commonpb.AnyValue) attribute.Value { arr := make([]int64, len(kv)) for i, v := range kv { - arr[i] = v.GetIntValue() + if v != nil { + arr[i] = v.GetIntValue() + } } return attribute.Int64SliceValue(arr) } func doubleArray(kv []*commonpb.AnyValue) attribute.Value { arr := make([]float64, len(kv)) for i, v := range kv { - arr[i] = v.GetDoubleValue() + if v != nil { + arr[i] = v.GetDoubleValue() + } } return attribute.Float64SliceValue(arr) } func stringArray(kv []*commonpb.AnyValue) attribute.Value { arr := make([]string, len(kv)) for i, v := range kv { - arr[i] = v.GetStringValue() + if v != nil { + arr[i] = v.GetStringValue() + } } return attribute.StringSliceValue(arr) } func arrayValues(kv []*commonpb.AnyValue) attribute.Value { - if len(kv) == 0 { + if len(kv) == 0 || kv[0] == nil { return attribute.StringSliceValue([]string{}) }
util/tracing/transform/span.go+19 −4 modified@@ -32,14 +32,20 @@ func Spans(sdl []*tracepb.ResourceSpans) []tracesdk.ReadOnlySpan { } for _, sdi := range sd.ScopeSpans { - sda := make([]tracesdk.ReadOnlySpan, len(sdi.Spans)) - for i, s := range sdi.Spans { - sda[i] = &readOnlySpan{ + if sdi == nil { + continue + } + sda := make([]tracesdk.ReadOnlySpan, 0, len(sdi.Spans)) + for _, s := range sdi.Spans { + if s == nil { + continue + } + sda = append(sda, &readOnlySpan{ pb: s, is: sdi.Scope, resource: sd.Resource, schemaURL: sd.SchemaUrl, - } + }) } out = append(out, sda...) } @@ -170,6 +176,9 @@ var _ tracesdk.ReadOnlySpan = &readOnlySpan{} // status transform a OTLP span status into span code. func statusCode(st *tracepb.Status) codes.Code { + if st == nil { + return codes.Unset + } switch st.Code { case tracepb.Status_STATUS_CODE_ERROR: return codes.Error @@ -186,6 +195,9 @@ func links(links []*tracepb.Span_Link) []tracesdk.Link { sl := make([]tracesdk.Link, 0, len(links)) for _, otLink := range links { + if otLink == nil { + continue + } // This redefinition is necessary to prevent otLink.*ID[:] copies // being reused -- in short we need a new otLink per iteration. otLink := otLink @@ -226,6 +238,9 @@ func spanEvents(es []*tracepb.Span_Event) []tracesdk.Event { if messageEvents >= maxMessageEventsPerSpan { break } + if e == nil { + continue + } messageEvents++ events = append(events, tracesdk.Event{
e1924dc32da3sourcepolicy: add validations for nil values
5 files changed · +137 −0
client/client_test.go+1 −0 modified@@ -210,6 +210,7 @@ func TestIntegration(t *testing.T) { testValidateInvalidConfig, testValidatePlatformsEmpty, testValidatePlatformsInvalid, + testValidateSourcePolicy, ) }
client/validation_test.go+102 −0 modified@@ -9,6 +9,7 @@ import ( "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/frontend/gateway/client" + sppb "github.com/moby/buildkit/sourcepolicy/pb" "github.com/moby/buildkit/util/testutil/integration" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/require" @@ -204,3 +205,104 @@ func testValidatePlatformsInvalid(t *testing.T, sb integration.Sandbox) { }) } } + +func testValidateSourcePolicy(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + + ctx := sb.Context() + + c, err := New(ctx, sb.Address()) + require.NoError(t, err) + defer c.Close() + + tcases := []struct { + name string + value *sppb.Policy + exp string + }{ + // this condition fails on marshaling atm + // { + // name: "nilrule", + // value: &sppb.Policy{ + // Rules: []*sppb.Rule{nil}, + // }, + // exp: "", + // }, + { + name: "nilselector", + value: &sppb.Policy{ + Rules: []*sppb.Rule{ + { + Action: sppb.PolicyAction_CONVERT, + }, + }, + }, + exp: "invalid nil selector in policy", + }, + { + name: "emptyaction", + value: &sppb.Policy{ + Rules: []*sppb.Rule{ + { + Action: sppb.PolicyAction(9000), + Selector: &sppb.Selector{ + Identifier: "docker-image://docker.io/library/alpine:latest", + }, + }, + }, + }, + exp: "unknown type", + }, + { + name: "nilupdates", + value: &sppb.Policy{ + Rules: []*sppb.Rule{ + { + Action: sppb.PolicyAction_CONVERT, + Selector: &sppb.Selector{ + Identifier: "docker-image://docker.io/library/alpine:latest", + }, + }, + }, + }, + exp: "missing destination for convert rule", + }, + } + + for _, tc := range tcases { + t.Run(tc.name, func(t *testing.T) { + + var viaFrontend bool + + b := func(ctx context.Context, c client.Client) (*client.Result, error) { + def, err := llb.Image("alpine").Marshal(ctx) + if err != nil { + return nil, err + } + + req := client.SolveRequest{ + Evaluate: true, + Definition: def.ToPB(), + } + if viaFrontend { + req.SourcePolicies = []*sppb.Policy{ + tc.value, + } + } + return c.Solve(ctx, req) + } + + _, err = c.Build(ctx, SolveOpt{ + SourcePolicy: tc.value, + }, "", b, nil) + require.Error(t, err) + require.Contains(t, err.Error(), tc.exp) + + viaFrontend = true + _, err = c.Build(ctx, SolveOpt{}, "", b, nil) + require.Error(t, err) + require.Contains(t, err.Error(), tc.exp) + + }) + } +}
solver/llbsolver/bridge.go+8 −0 modified@@ -79,6 +79,14 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp } var polEngine SourcePolicyEvaluator if srcPol != nil || len(pol) > 0 { + for _, p := range pol { + if p == nil { + return nil, errors.Errorf("invalid nil policy") + } + if err := validateSourcePolicy(*p); err != nil { + return nil, err + } + } if srcPol != nil { pol = append([]*spb.Policy{srcPol}, pol...) }
solver/llbsolver/solver.go+23 −0 modified@@ -447,6 +447,9 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro j.SetValue(keyEntitlements, set) if srcPol != nil { + if err := validateSourcePolicy(*srcPol); err != nil { + return nil, err + } j.SetValue(keySourcePolicy, *srcPol) } @@ -595,6 +598,23 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro }, nil } +func validateSourcePolicy(pol spb.Policy) error { + for _, r := range pol.Rules { + if r == nil { + return errors.New("invalid nil rule in policy") + } + if r.Selector == nil { + return errors.New("invalid nil selector in policy") + } + for _, c := range r.Selector.Constraints { + if c == nil { + return errors.New("invalid nil constraint in policy") + } + } + } + return nil +} + func runCacheExporters(ctx context.Context, exporters []RemoteCacheExporter, j *solver.Job, cached *result.Result[solver.CachedResult], inp *result.Result[cache.ImmutableRef]) (map[string]string, error) { eg, ctx := errgroup.WithContext(ctx) g := session.NewGroup(j.SessionID) @@ -991,6 +1011,9 @@ func loadSourcePolicy(b solver.Builder) (*spb.Policy, error) { return errors.Errorf("invalid source policy %T", v) } for _, f := range x.Rules { + if f == nil { + return errors.Errorf("invalid nil policy rule") + } r := *f srcPol.Rules = append(srcPol.Rules, &r) }
sourcepolicy/matcher.go+3 −0 modified@@ -10,6 +10,9 @@ import ( func match(ctx context.Context, src *selectorCache, ref string, attrs map[string]string) (bool, error) { for _, c := range src.Constraints { + if c == nil { + return false, errors.Errorf("invalid nil constraint for %v", src) + } switch c.Condition { case spb.AttrMatch_EQUAL: if attrs[c.Key] != c.Value {
96663dd35bf3exporter: add validation for platforms key value
3 files changed · +124 −0
client/client_test.go+2 −0 modified@@ -208,6 +208,8 @@ func TestIntegration(t *testing.T) { testExportLocalNoPlatformSplitOverwrite, testValidateNullConfig, testValidateInvalidConfig, + testValidatePlatformsEmpty, + testValidatePlatformsInvalid, ) }
client/validation_test.go+108 −0 modified@@ -7,6 +7,7 @@ import ( "testing" "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/util/testutil/integration" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" @@ -96,3 +97,110 @@ func testValidateInvalidConfig(t *testing.T, sb integration.Sandbox) { require.Error(t, err) require.Contains(t, err.Error(), "invalid image config for export: missing os") } + +func testValidatePlatformsEmpty(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + + ctx := sb.Context() + + c, err := New(ctx, sb.Address()) + require.NoError(t, err) + defer c.Close() + + b := func(ctx context.Context, c client.Client) (*client.Result, error) { + def, err := llb.Scratch().Marshal(ctx) + if err != nil { + return nil, err + } + + res, err := c.Solve(ctx, client.SolveRequest{ + Evaluate: true, + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + res.AddMeta("refs.platforms", []byte("null")) + return res, nil + } + + _, err = c.Build(ctx, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterOCI, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }, + }, + }, "", b, nil) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid empty platforms index for exporter") +} + +func testValidatePlatformsInvalid(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + + ctx := sb.Context() + + c, err := New(ctx, sb.Address()) + require.NoError(t, err) + defer c.Close() + + tcases := []struct { + name string + value []exptypes.Platform + exp string + }{ + { + name: "emptyID", + value: []exptypes.Platform{{}}, + exp: "invalid empty platform key for exporter", + }, + { + name: "missingOS", + value: []exptypes.Platform{ + { + ID: "foo", + }, + }, + exp: "invalid platform value", + }, + } + + for _, tc := range tcases { + t.Run(tc.name, func(t *testing.T) { + b := func(ctx context.Context, c client.Client) (*client.Result, error) { + def, err := llb.Scratch().Marshal(ctx) + if err != nil { + return nil, err + } + + res, err := c.Solve(ctx, client.SolveRequest{ + Evaluate: true, + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + + dt, err := json.Marshal(exptypes.Platforms{Platforms: tc.value}) + if err != nil { + return nil, err + } + + res.AddMeta("refs.platforms", dt) + return res, nil + } + + _, err = c.Build(ctx, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterOCI, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }, + }, + }, "", b, nil) + require.Error(t, err) + require.Contains(t, err.Error(), tc.exp) + }) + } +}
exporter/containerimage/exptypes/parse.go+14 −0 modified@@ -17,6 +17,18 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) { return Platforms{}, errors.Wrapf(err, "failed to parse platforms passed to provenance processor") } } + if len(ps.Platforms) == 0 { + return Platforms{}, errors.Errorf("invalid empty platforms index for exporter") + } + for i, p := range ps.Platforms { + if p.ID == "" { + return Platforms{}, errors.Errorf("invalid empty platform key for exporter") + } + if p.Platform.OS == "" || p.Platform.Architecture == "" { + return Platforms{}, errors.Errorf("invalid platform value %v for exporter", p.Platform) + } + ps.Platforms[i].Platform = platforms.Normalize(p.Platform) + } return ps, nil } @@ -36,6 +48,8 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) { OSFeatures: img.OSFeatures, Variant: img.Variant, } + } else if img.OS != "" || img.Architecture != "" { + return Platforms{}, errors.Errorf("invalid image config: os and architecture must be specified together") } } p = platforms.Normalize(p)
481d9c45f473exporter: add validation for invalid platorm
3 files changed · +59 −0
client/client_test.go+4 −0 modified@@ -207,6 +207,7 @@ func TestIntegration(t *testing.T) { testExportLocalNoPlatformSplit, testExportLocalNoPlatformSplitOverwrite, testValidateNullConfig, + testValidateInvalidConfig, ) } @@ -8490,6 +8491,7 @@ cat <<EOF > $BUILDKIT_SCAN_DESTINATION/spdx.json EOF ` img.Config.Cmd = []string{"/bin/sh", "-c", cmd} + img.Platform = p config, err := json.Marshal(img) if err != nil { return nil, errors.Wrapf(err, "failed to marshal image config") @@ -8768,6 +8770,7 @@ cat <<EOF > $BUILDKIT_SCAN_DESTINATION/spdx.json EOF ` img.Config.Cmd = []string{"/bin/sh", "-c", cmd} + img.Platform = p config, err := json.Marshal(img) if err != nil { return nil, errors.Wrapf(err, "failed to marshal image config") @@ -8820,6 +8823,7 @@ EOF var img ocispecs.Image img.Config.Cmd = []string{"/bin/sh", "-c", "cat /greeting"} + img.Platform = p config, err := json.Marshal(img) if err != nil { return nil, errors.Wrapf(err, "failed to marshal image config")
client/validation_test.go+48 −0 modified@@ -2,12 +2,14 @@ package client import ( "context" + "encoding/json" "io" "testing" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/util/testutil/integration" + ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/require" ) @@ -48,3 +50,49 @@ func testValidateNullConfig(t *testing.T, sb integration.Sandbox) { require.Error(t, err) require.Contains(t, err.Error(), "invalid null image config for export") } + +func testValidateInvalidConfig(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + + ctx := sb.Context() + + c, err := New(ctx, sb.Address()) + require.NoError(t, err) + defer c.Close() + + b := func(ctx context.Context, c client.Client) (*client.Result, error) { + def, err := llb.Scratch().Marshal(ctx) + if err != nil { + return nil, err + } + + res, err := c.Solve(ctx, client.SolveRequest{ + Evaluate: true, + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + var img ocispecs.Image + img.Platform = ocispecs.Platform{ + Architecture: "amd64", + } + dt, err := json.Marshal(img) + if err != nil { + return nil, err + } + res.AddMeta("containerimage.config", dt) + return res, nil + } + + _, err = c.Build(ctx, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterOCI, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }, + }, + }, "", b, nil) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid image config for export: missing os") +}
exporter/containerimage/writer.go+7 −0 modified@@ -583,6 +583,13 @@ func patchImageConfig(dt []byte, descs []ocispecs.Descriptor, history []ocispecs return nil, errors.Errorf("invalid null image config for export") } + if img.OS == "" { + return nil, errors.Errorf("invalid image config for export: missing os") + } + if img.Architecture == "" { + return nil, errors.Errorf("invalid image config for export: missing architecture") + } + var rootFS ocispecs.RootFS rootFS.Type = "layers" for _, desc := range descs {
83edaef59d54exporter: validate null config metadata from gateway
3 files changed · +60 −0
client/client_test.go+1 −0 modified@@ -206,6 +206,7 @@ func TestIntegration(t *testing.T) { testMultipleRecordsWithSameLayersCacheImportExport, testExportLocalNoPlatformSplit, testExportLocalNoPlatformSplitOverwrite, + testValidateNullConfig, ) }
client/validation_test.go+50 −0 added@@ -0,0 +1,50 @@ +package client + +import ( + "context" + "io" + "testing" + + "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/util/testutil/integration" + "github.com/stretchr/testify/require" +) + +func testValidateNullConfig(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + + ctx := sb.Context() + + c, err := New(ctx, sb.Address()) + require.NoError(t, err) + defer c.Close() + + b := func(ctx context.Context, c client.Client) (*client.Result, error) { + def, err := llb.Scratch().Marshal(ctx) + if err != nil { + return nil, err + } + + res, err := c.Solve(ctx, client.SolveRequest{ + Evaluate: true, + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + res.AddMeta("containerimage.config", []byte("null")) + return res, nil + } + + _, err = c.Build(ctx, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterOCI, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }, + }, + }, "", b, nil) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid null image config for export") +}
exporter/containerimage/writer.go+9 −0 modified@@ -569,11 +569,20 @@ func parseHistoryFromConfig(dt []byte) ([]ocispecs.History, error) { } func patchImageConfig(dt []byte, descs []ocispecs.Descriptor, history []ocispecs.History, cache []byte, epoch *time.Time) ([]byte, error) { + var img ocispecs.Image + if err := json.Unmarshal(dt, &img); err != nil { + return nil, errors.Wrap(err, "invalid image config for export") + } + m := map[string]json.RawMessage{} if err := json.Unmarshal(dt, &m); err != nil { return nil, errors.Wrap(err, "failed to parse image config for patch") } + if m == nil { + return nil, errors.Errorf("invalid null image config for export") + } + var rootFS ocispecs.RootFS rootFS.Type = "layers" for _, desc := range descs {
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
10- github.com/advisories/GHSA-9p26-698r-w4hxghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-23650ghsaADVISORY
- github.com/moby/buildkit/commit/481d9c45f473c58537f39694a38d7995cc656987ghsaWEB
- github.com/moby/buildkit/commit/7718bd5c3dc8fc5cd246a30cc41766e7a53c043cghsaWEB
- github.com/moby/buildkit/commit/83edaef59d545b93e2750f1f85675a3764593feeghsaWEB
- github.com/moby/buildkit/commit/96663dd35bf3787d7efb1ee7fd9ac7fe533582aeghsaWEB
- github.com/moby/buildkit/commit/e1924dc32da35bfb0bfdbb9d0fc7bca25e552330ghsaWEB
- github.com/moby/buildkit/pull/4601ghsax_refsource_MISCWEB
- github.com/moby/buildkit/releases/tag/v0.12.5ghsax_refsource_MISCWEB
- github.com/moby/buildkit/security/advisories/GHSA-9p26-698r-w4hxghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.