Repository: moby/buildkit

Issue:
flaky test:  TestIntegration/slice=1-4/TestCachedMounts/worker=containerd
https://github.com/moby/buildkit/actions/runs/14379949876/job/40321264606?pr=5904#step:8:544

```
=== FAIL: client TestIntegration/slice=1-4/TestCachedMounts/worker=containerd (25.87s)
    client_test.go:6846: 
        	Error Trace:	D:/a/buildkit/buildkit/client/client_test.go:6846
        	            				D:/a/buildkit/buildkit/util/testutil/integration/run.go:103
        	            				D:/a/buildkit/buildkit/util/testutil/integration/run.go:245
        	Error:      	Received unexpected error:
        	            	failed to compute cache key: failed to calculate checksum of ref lht661ikl1n3ucv52eoq4btsi::zpg95ubmeb1yebc6liy6klxco: failed to open /WcSandboxState/Hives/DefaultUser_Delta: open C:\Users\RUNNER~1\AppData\Local\Temp\buildkit-mount3558833864\WcSandboxState\Hives\DefaultUser_Delta: Access is denied.
        	            	github.com/moby/buildkit/util/stack.Enable
        	            		D:/a/buildkit/buildkit/util/stack/stack.go:82
        	            	github.com/moby/buildkit/util/grpcerrors.FromGRPC
        	            		D:/a/buildkit/buildkit/util/grpcerrors/grpcerrors.go:205
        	            	github.com/moby/buildkit/util/grpcerrors.UnaryClientInterceptor
        	            		D:/a/buildkit/buildkit/util/grpcerrors/intercept.go:41
        	            	google.golang.org/grpc.(*ClientConn).Invoke
        	            		D:/a/buildkit/buildkit/vendor/google.golang.org/grpc/call.go:35
        	            	github.com/moby/buildkit/api/services/control.(*controlClient).Solve
        	            		D:/a/buildkit/buildkit/api/services/control/control_grpc.pb.go:88
        	            	github.com/moby/buildkit/client.(*Client).solve.func2
        	            		D:/a/buildkit/buildkit/client/solve.go:267
        	            	golang.org/x/sync/errgroup.(*Group).Go.func1
        	            		D:/a/buildkit/buildkit/vendor/golang.org/x/sync/errgroup/errgroup.go:79
        	            	runtime.goexit
        	            		C:/hostedtoolcache/windows/go/1.23.8/x64/src/runtime/asm_amd64.s:1700
        	            	failed to solve
        	            	github.com/moby/buildkit/client.(*Client).solve.func2
        	            		D:/a/buildkit/buildkit/client/solve.go:283
        	            	golang.org/x/sync/errgroup.(*Group).Go.func1
        	            		D:/a/buildkit/buildkit/vendor/golang.org/x/sync/errgroup/errgroup.go:79
        	            	runtime.goexit
        	            		C:/hostedtoolcache/windows/go/1.23.8/x64/src/runtime/asm_amd64.s:1700
        	Test:       	TestIntegration/slice=1-4/TestCachedMounts/worker=containerd
```

Discussion:
@profnandaa: Taking a look.@profnandaa: Adding the stack-trace of where the error originates:
```
  sandbox.go:205: github.com/moby/buildkit/cache/contenthash.prepareDigest
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:1219
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).checksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:930
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).checksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:898
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).checksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:898
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).checksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:898
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).scanChecksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:859
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).lazyChecksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:822
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).Checksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:426
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheManager).Checksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:117
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.Checksum
    sandbox.go:205: 	/src/cache/contenthash/checksum.go:65
    sandbox.go:205: github.com/moby/buildkit/solver/llbsolver/ops.(*ExecOp).CacheMap.NewContentHashFunc.func2.1
    sandbox.go:205: 	/src/solver/llbsolver/ops/opsutils/contenthash.go:47
    sandbox.go:205: golang.org/x/sync/errgroup.(*Group).Go.func1
    sandbox.go:205: 	/src/vendor/golang.org/x/sync/errgroup/errgroup.go:79
    sandbox.go:205: runtime.goexit
    sandbox.go:205: 	/usr/local/go/src/runtime/asm_amd64.s:1700
```@profnandaa: This failure has resuffaced here too - https://github.com/moby/buildkit/actions/runs/14802211583/job/41563473233?pr=5955

Setting some time this week to dig into this. Sorry had to complete on some other stuff that took long.@profnandaa: Repro steps:

```powershell
$cmd = "go test --count=1 -v --run=TestIntegration/TestCachedMounts/worker=containerd ./client"
for ($i = 1; $i -le 100; $i++) { iex $cmd }
```@profnandaa: **UPDATE:**

This happens just right after the privilege is disabled, some sort of a race condition. Added a log-line to see:

```
    sandbox.go:205: time="2025-05-19T04:24:05-07:00" level=info msg="===> Privilege disabled!!"
    sandbox.go:205: time="2025-05-19T04:24:06-07:00" level=error msg="/moby.buildkit.v1.Control/Solve returned error: rpc error: code = Unknown desc = failed to compute cache key: failed to calculate checksum of ref szz6mcq63r4fsfhs4y4ynctw6::idei7kbxkyrnqp1h3nibcnfar: failed to open /WcSandboxState/Hives/DefaultUser_Delta: open C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\2\\buildkit-mount3029327637\\WcSandboxState\\Hives\\DefaultUser_Delta: Access is denied." spanID=07037f166d560fcd traceID=61696a44866dc0511eaed677506bb6c2
    sandbox.go:205: failed to compute cache key: failed to calculate checksum of ref szz6mcq63r4fsfhs4y4ynctw6::idei7kbxkyrnqp1h3nibcnfar: failed to open /WcSandboxState/Hives/DefaultUser_Delta: open C:\Users\ADMINI~1\AppData\Local\Temp\2\buildkit-mount3029327637\WcSandboxState\Hives\DefaultUser_Delta: Access is denied.
    sandbox.go:205: 6392 v0.0.0+unknown buildkitd --containerd-worker-gc=false --containerd-worker=true --containerd-worker-addr npipe:////./pipe/containerd-bktest_containerd1745300450 --containerd-worker-labels=org.mobyproject.buildkit.worker.sandbox=true --config=C:\Users\ADMINI~1\AppData\Local\Temp\2\bktest_config1107440939\buildkitd.toml --root C:\Users\ADMINI~1\AppData\Local\Temp\2\bktest_buildkitd925949042 --addr npipe:////./pipe/buildkitd-bktest_buildkitd925949042 --debug
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.prepareDigest
    sandbox.go:205: 	C:/dev/buildkit/cache/contenthash/checksum.go:1216
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).checksum
    sandbox.go:205: 	C:/dev/buildkit/cache/contenthash/checksum.go:927
    sandbox.go:205: github.com/moby/buildkit/cache/contenthash.(*cacheContext).checksum
```

Solution patch:
diff --git a/.golangci.yml b/.golangci.yml
index 3acba40cf..2efd20f86 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,18 +1,18 @@
+version: "2"
 run:
-  timeout: 30m
   modules-download-mode: vendor
-
 linters:
+  default: none
   enable:
     - bodyclose
     - depguard
+    - durationcheck
     - errname
+    - errorlint
+    - fatcontext
     - forbidigo
     - gocritic
-    - gofmt
-    - goimports
     - gosec
-    - gosimple
     - govet
     - importas
     - ineffassign
@@ -23,105 +23,108 @@ linters:
     - revive
     - staticcheck
     - testifylint
-    - typecheck
     - unused
+    - usestdlibvars
     - whitespace
-  disable-all: true
-
-linters-settings:
-  staticcheck:
-    checks:
-      - "all"
-  gocritic:
-    disabled-checks:
-      - "ifElseChain"
-      - "assignOp"
-      - "appendAssign"
-      - "singleCaseSwitch"
-  govet:
-    enable:
-      - nilness
-      - unusedwrite
-  # enable-all: true
-  # disable:
-  #   - fieldalignment
-  #   - shadow
-  depguard:
+  settings:
+    depguard:
+      rules:
+        main:
+          deny:
+            - pkg: github.com/containerd/containerd/errdefs
+              desc: The containerd errdefs package was migrated to a separate module. Use github.com/containerd/errdefs instead.
+            - pkg: github.com/containerd/containerd/log
+              desc: The containerd log package was migrated to a separate module. Use github.com/containerd/log instead.
+            - pkg: github.com/containerd/containerd/pkg/userns
+              desc: Use github.com/moby/sys/userns instead.
+            - pkg: github.com/containerd/containerd/platforms
+              desc: The containerd platforms package was migrated to a separate module. Use github.com/containerd/platforms instead.
+            - pkg: github.com/containerd/nydus-snapshotter/pkg/errdefs
+              desc: You probably meant to use github.com/containerd/errdefs
+            - pkg: github.com/opencontainers/runc/libcontainer/userns
+              desc: Use github.com/moby/sys/userns instead.
+            - pkg: io/ioutil
+              desc: The io/ioutil package has been deprecated.
+    forbidigo:
+      forbid:
+        - pattern: ^context\.WithCancel(# use context\.WithCancelCause instead)?$
+        - pattern: ^context\.WithDeadline(# use context\.WithDeadline instead)?$
+        - pattern: ^context\.WithTimeout(# use context\.WithTimeoutCause instead)?$
+        - pattern: ^ctx\.Err(# use context\.Cause instead)?$
+        - pattern: ^fmt\.Errorf(# use errors\.Errorf instead)?$
+        - pattern: ^logrus\.(Trace|Debug|Info|Warn|Warning|Error|Fatal)(f|ln)?(# use bklog\.G or bklog\.L instead of logrus directly)?$
+        - pattern: ^platforms\.DefaultString(# use platforms\.Format(platforms\.DefaultSpec()) instead\. Be aware that DefaultSpec is for the local platform, so must be avoided when working cross-platform)?$
+    gocritic:
+      disabled-checks:
+        - ifElseChain
+        - assignOp
+        - appendAssign
+        - singleCaseSwitch
+    gosec:
+      excludes:
+        - G101
+        - G402
+        - G504
+        - G601
+        - G115
+      config:
+        G306: "0644"
+    govet:
+      enable:
+        - nilness
+        - unusedwrite
+    importas:
+      alias:
+        - pkg: github.com/containerd/errdefs
+          alias: cerrdefs
+        - pkg: github.com/opencontainers/image-spec/specs-go/v1
+          alias: ocispecs
+        - pkg: github.com/opencontainers/go-digest
+          alias: digest
+      no-unaliased: true
+    staticcheck:
+      checks:
+        - all
+    testifylint:
+      disable:
+        - empty
+        - bool-compare
+        - len
+        - negative-positive
+  exclusions:
+    generated: lax
+    presets:
+      - comments
+      - common-false-positives
+      - legacy
+      - std-error-handling
     rules:
-      main:
-        deny:
-          - pkg: "github.com/containerd/containerd/errdefs"
-            desc: The containerd errdefs package was migrated to a separate module. Use github.com/containerd/errdefs instead.
-          - pkg: "github.com/containerd/containerd/log"
-            desc: The containerd log package was migrated to a separate module. Use github.com/containerd/log instead.
-          - pkg: "github.com/containerd/containerd/pkg/userns"
-            desc: Use github.com/moby/sys/userns instead.
-          - pkg: "github.com/containerd/containerd/platforms"
-            desc: The containerd platforms package was migrated to a separate module. Use github.com/containerd/platforms instead.
-          - pkg: "github.com/containerd/nydus-snapshotter/pkg/errdefs"
-            desc: You probably meant to use github.com/containerd/errdefs
-          - pkg: "github.com/opencontainers/runc/libcontainer/userns"
-            desc: Use github.com/moby/sys/userns instead.
-          - pkg: "io/ioutil"
-            desc: The io/ioutil package has been deprecated.
-  forbidigo:
-    forbid:
-      - '^context\.WithCancel(# use context\.WithCancelCause instead)?$'
-      - '^context\.WithDeadline(# use context\.WithDeadline instead)?$'
-      - '^context\.WithTimeout(# use context\.WithTimeoutCause instead)?$'
-      - '^ctx\.Err(# use context\.Cause instead)?$'
-      - '^fmt\.Errorf(# use errors\.Errorf instead)?$'
-      - '^logrus\.(Trace|Debug|Info|Warn|Warning|Error|Fatal)(f|ln)?(# use bklog\.G or bklog\.L instead of logrus directly)?$'
-      - '^platforms\.DefaultString(# use platforms\.Format(platforms\.DefaultSpec()) instead\. Be aware that DefaultSpec is for the local platform, so must be avoided when working cross-platform)?$'
-  importas:
-    alias:
-      # Enforce alias to prevent it accidentally being used instead of our
-      # own errdefs package (or vice-versa).
-      - pkg: "github.com/containerd/errdefs"
-        alias: "cerrdefs"
-      - pkg: "github.com/opencontainers/image-spec/specs-go/v1"
-        alias: "ocispecs"
-      - pkg: "github.com/opencontainers/go-digest"
-        alias: "digest"
-
-    # Do not allow unaliased imports of aliased packages.
-    no-unaliased: true
-  gosec:
-    excludes:
-      - G101  # Potential hardcoded credentials (false positives)
-      - G402  # TLS MinVersion too low
-      - G504  # Import blocklist: net/http/cgi
-      - G601  # Implicit memory aliasing in for loop (false positives)
-      - G115  # integer overflow conversion (TODO: verify these)
-    config:
-      G306: "0644"
-  testifylint:
-    disable:
-      # disable rules that reduce the test condition
-      - "empty"
-      - "bool-compare"
-      - "len"
-      - "negative-positive"
-
-issues:
-  exclude-files:
-    - ".*\\.pb\\.go$"
-  exclude-rules:
-    - linters:
-        - revive
-      text: "stutters"
-    - linters:
-        - revive
-      text: "empty-block"
-    - linters:
-        - revive
-      text: "superfluous-else"
-    - linters:
-        - revive
-      text: "unused-parameter"
-    - linters:
-        - revive
-      text: "redefines-builtin-id"
-    - linters:
-        - revive
-      text: "if-return"
+      - linters:
+          - revive
+        text: stutters
+      - linters:
+          - revive
+        text: empty-block
+      - linters:
+          - revive
+        text: superfluous-else
+      - linters:
+          - revive
+        text: unused-parameter
+      - linters:
+          - revive
+        text: redefines-builtin-id
+      - linters:
+          - revive
+        text: if-return
+    paths:
+      - .*\.pb\.go$
+      - examples
+formatters:
+  enable:
+    - gofmt
+    - goimports
+  exclusions:
+    generated: lax
+    paths:
+      - .*\.pb\.go$
diff --git a/cache/blobs.go b/cache/blobs.go
index ba5889217..87cf5f2fb 100644
--- a/cache/blobs.go
+++ b/cache/blobs.go
@@ -351,7 +351,7 @@ func (sr *immutableRef) computeChainMetadata(ctx context.Context, filter map[str
 		}
 		diffID := sr.getDiffID()
 		chainID = diffID
-		blobChainID = imagespecidentity.ChainID([]digest.Digest{digest.Digest(sr.getBlob()), diffID})
+		blobChainID = imagespecidentity.ChainID([]digest.Digest{sr.getBlob(), diffID})
 	case Layer:
 		if _, ok := filter[sr.ID()]; !ok {
 			return nil
@@ -368,9 +368,9 @@ func (sr *immutableRef) computeChainMetadata(ctx context.Context, filter map[str
 				return errors.Errorf("failed to set blobchain for reference with non-addressable parent %q", sr.layerParent.GetDescription())
 			}
 		}
-		diffID := digest.Digest(sr.getDiffID())
+		diffID := sr.getDiffID()
 		chainID = imagespecidentity.ChainID([]digest.Digest{chainID, diffID})
-		blobID := imagespecidentity.ChainID([]digest.Digest{digest.Digest(sr.getBlob()), diffID})
+		blobID := imagespecidentity.ChainID([]digest.Digest{sr.getBlob(), diffID})
 		blobChainID = imagespecidentity.ChainID([]digest.Digest{blobChainID, blobID})
 	case Merge:
 		baseInput := sr.mergeParents[0]
@@ -386,9 +386,9 @@ func (sr *immutableRef) computeChainMetadata(ctx context.Context, filter map[str
 					// not enough information to compute chain at this time
 					return nil
 				}
-				diffID := digest.Digest(layer.getDiffID())
+				diffID := layer.getDiffID()
 				chainID = imagespecidentity.ChainID([]digest.Digest{chainID, diffID})
-				blobID := imagespecidentity.ChainID([]digest.Digest{digest.Digest(layer.getBlob()), diffID})
+				blobID := imagespecidentity.ChainID([]digest.Digest{layer.getBlob(), diffID})
 				blobChainID = imagespecidentity.ChainID([]digest.Digest{blobChainID, blobID})
 			}
 		}
@@ -397,7 +397,7 @@ func (sr *immutableRef) computeChainMetadata(ctx context.Context, filter map[str
 			// this diff is its own blob
 			diffID := sr.getDiffID()
 			chainID = diffID
-			blobChainID = imagespecidentity.ChainID([]digest.Digest{digest.Digest(sr.getBlob()), diffID})
+			blobChainID = imagespecidentity.ChainID([]digest.Digest{sr.getBlob(), diffID})
 		} else {
 			// re-using upper blob
 			chainID = sr.diffParents.upper.getChainID()
diff --git a/cache/blobs_linux.go b/cache/blobs_linux.go
index 1b70d1089..07f0300e8 100644
--- a/cache/blobs_linux.go
+++ b/cache/blobs_linux.go
@@ -45,7 +45,7 @@ func (sr *immutableRef) tryComputeOverlayBlob(ctx context.Context, lower, upper
 
 	defer func() {
 		if cw != nil {
-			ctx = context.WithoutCancel(ctx)
+			ctx := context.WithoutCancel(ctx)
 			// after commit success cw will be set to nil, if cw isn't nil, error
 			// happened before commit, we should abort this ingest, and because the
 			// error may incured by ctx cancel, use a new context here. And since
diff --git a/cache/contenthash/checksum.go b/cache/contenthash/checksum.go
index 164769206..d2c6b0118 100644
--- a/cache/contenthash/checksum.go
+++ b/cache/contenthash/checksum.go
@@ -399,7 +399,7 @@ func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.Fil
 			for _, l := range links {
 				pp := convertKeyToPath(l)
 				cc.txn.Insert(l, cr)
-				d := path.Dir(string(pp))
+				d := path.Dir(pp)
 				if d == "/" {
 					d = ""
 				}
@@ -774,11 +774,11 @@ func splitWildcards(p string) (d1, d2 string) {
 
 func containsWildcards(name string) bool {
 	for i := 0; i < len(name); i++ {
-		ch := name[i]
-		if ch == '\\' {
-			i++
-		} else if ch == '*' || ch == '?' || ch == '[' {
+		switch name[i] {
+		case '*', '?', '[':
 			return true
+		case '\\':
+			i++
 		}
 	}
 	return false
@@ -887,10 +887,7 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node[*CacheRe
 		iter.SeekLowerBound(append(slices.Clone(next), 0))
 		subk := next
 		ok := true
-		for {
-			if !ok || !bytes.HasPrefix(subk, next) {
-				break
-			}
+		for ok && bytes.HasPrefix(subk, next) {
 			h.Write(bytes.TrimPrefix(subk, k))
 
 			// We do not follow trailing links when checksumming a directory's
diff --git a/cache/contenthash/filehash.go b/cache/contenthash/filehash.go
index 64df7e8d3..460efa9ef 100644
--- a/cache/contenthash/filehash.go
+++ b/cache/contenthash/filehash.go
@@ -93,7 +93,7 @@ type statInfo struct {
 }
 
 func (s *statInfo) Name() string {
-	return filepath.Base(s.Stat.Path)
+	return filepath.Base(s.Path)
 }
 
 func (s *statInfo) Size() int64 {
diff --git a/cache/manager.go b/cache/manager.go
index 0bd285d1a..c7ab50df6 100644
--- a/cache/manager.go
+++ b/cache/manager.go
@@ -1427,10 +1427,7 @@ func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo)
 	}
 	cm.mu.Unlock()
 
-	for {
-		if len(rescan) == 0 {
-			break
-		}
+	for len(rescan) != 0 {
 		for id := range rescan {
 			v := m[id]
 			if v.refs == 0 {
diff --git a/cache/metadata.go b/cache/metadata.go
index 3a25b3d07..603e40067 100644
--- a/cache/metadata.go
+++ b/cache/metadata.go
@@ -406,11 +406,11 @@ func (md *cacheMetadata) getLastUsed() (int, *time.Time) {
 	if v == nil {
 		return usageCount, nil
 	}
-	var lastUsedTs int64
-	if err := v.Unmarshal(&lastUsedTs); err != nil || lastUsedTs == 0 {
+	var lastUsedTS int64
+	if err := v.Unmarshal(&lastUsedTS); err != nil || lastUsedTS == 0 {
 		return usageCount, nil
 	}
-	tm := time.Unix(lastUsedTs/1e9, lastUsedTs%1e9)
+	tm := time.Unix(lastUsedTS/1e9, lastUsedTS%1e9)
 	return usageCount, &tm
 }
 
diff --git a/cache/migrate_v2.go b/cache/migrate_v2.go
index 184abb556..67aed2d5e 100644
--- a/cache/migrate_v2.go
+++ b/cache/migrate_v2.go
@@ -223,7 +223,7 @@ func MigrateV2(ctx context.Context, from, to string, cs content.Store, s snapsho
 
 			if blob := md.getBlob(); blob != "" {
 				if _, err := cs.Update(ctx, content.Info{
-					Digest: digest.Digest(blob),
+					Digest: blob,
 				}, "labels.containerd.io/gc.root"); err != nil {
 					return err
 				}
diff --git a/cache/opts.go b/cache/opts.go
index b2ddbb6e2..400ac21a9 100644
--- a/cache/opts.go
+++ b/cache/opts.go
@@ -30,7 +30,7 @@ func descHandlersOf(opts ...RefOption) DescHandlers {
 
 type DescHandlerKey digest.Digest
 
-type NeedsRemoteProviderError []digest.Digest //nolint:errname
+type NeedsRemoteProviderError []digest.Digest
 
 func (m NeedsRemoteProviderError) Error() string {
 	return fmt.Sprintf("missing descriptor handlers for lazy blobs %+v", []digest.Digest(m))
diff --git a/cache/refs.go b/cache/refs.go
index 8752ce1de..eeee69dad 100644
--- a/cache/refs.go
+++ b/cache/refs.go
@@ -188,7 +188,7 @@ func (p parentRefs) release(ctx context.Context) (rerr error) {
 	return rerr
 }
 
-func (p parentRefs) clone() parentRefs {
+func (p parentRefs) cloneParentRefs() parentRefs {
 	switch {
 	case p.layerParent != nil:
 		p.layerParent = p.layerParent.clone()
@@ -361,12 +361,12 @@ func (cr *cacheRecord) size(ctx context.Context) (int64, error) {
 		}
 		if dgst := cr.getBlob(); dgst != "" {
 			added := make(map[digest.Digest]struct{})
-			info, err := cr.cm.ContentStore.Info(ctx, digest.Digest(dgst))
+			info, err := cr.cm.ContentStore.Info(ctx, dgst)
 			if err == nil {
 				usage.Size += info.Size
-				added[digest.Digest(dgst)] = struct{}{}
+				added[dgst] = struct{}{}
 			}
-			walkBlobVariantsOnly(ctx, cr.cm.ContentStore, digest.Digest(dgst), func(desc ocispecs.Descriptor) bool {
+			walkBlobVariantsOnly(ctx, cr.cm.ContentStore, dgst, func(desc ocispecs.Descriptor) bool {
 				if _, ok := added[desc.Digest]; !ok {
 					if info, err := cr.cm.ContentStore.Info(ctx, desc.Digest); err == nil {
 						usage.Size += info.Size
@@ -472,7 +472,7 @@ func (cr *cacheRecord) remove(ctx context.Context, removeSnapshot bool) (rerr er
 	if err := cr.cm.MetadataStore.Clear(cr.ID()); err != nil {
 		return errors.Wrapf(err, "failed to delete metadata of %s", cr.ID())
 	}
-	if err := cr.parentRefs.release(ctx); err != nil {
+	if err := cr.release(ctx); err != nil {
 		return errors.Wrapf(err, "failed to release parents of %s", cr.ID())
 	}
 	return nil
@@ -1035,7 +1035,7 @@ func (sr *immutableRef) withRemoteSnapshotLabelsStargzMode(ctx context.Context,
 		} else if _, ok := info.Labels["containerd.io/snapshot/remote"]; !ok {
 			continue // This isn't a remote snapshot; skip
 		}
-		dh := dhs[digest.Digest(r.getBlob())]
+		dh := dhs[r.getBlob()]
 		if dh == nil {
 			continue // no info passed; skip
 		}
@@ -1075,7 +1075,7 @@ func (sr *immutableRef) prepareRemoteSnapshotsStargzMode(ctx context.Context, s
 				continue
 			}
 
-			dh := dhs[digest.Digest(r.getBlob())]
+			dh := dhs[r.getBlob()]
 			if dh == nil {
 				// We cannot prepare remote snapshots without descHandler.
 				return nil, nil
@@ -1479,7 +1479,7 @@ func (sr *mutableRef) commit() (_ *immutableRef, rerr error) {
 	rec := &cacheRecord{
 		mu:            sr.mu,
 		cm:            sr.cm,
-		parentRefs:    sr.parentRefs.clone(),
+		parentRefs:    sr.cloneParentRefs(),
 		equalMutable:  sr,
 		refs:          make(map[ref]struct{}),
 		cacheMetadata: md,
diff --git a/cache/remotecache/azblob/exporter.go b/cache/remotecache/azblob/exporter.go
index 84729adff..e95c3d35a 100644
--- a/cache/remotecache/azblob/exporter.go
+++ b/cache/remotecache/azblob/exporter.go
@@ -153,7 +153,7 @@ func (ce *exporter) uploadManifest(ctx context.Context, manifestKey string, read
 	blobClient := ce.containerClient.NewBlockBlobClient(manifestKey)
 
 	ctx, cnclFn := context.WithCancelCause(ctx)
-	ctx, _ = context.WithTimeoutCause(ctx, time.Minute*5, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, time.Minute*5, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer cnclFn(errors.WithStack(context.Canceled))
 
 	_, err := blobClient.Upload(ctx, reader, &blockblob.UploadOptions{})
@@ -171,7 +171,7 @@ func (ce *exporter) uploadBlobIfNotExists(ctx context.Context, blobKey string, r
 	blobClient := ce.containerClient.NewBlockBlobClient(blobKey)
 
 	uploadCtx, cnclFn := context.WithCancelCause(ctx)
-	uploadCtx, _ = context.WithTimeoutCause(uploadCtx, time.Minute*5, errors.WithStack(context.DeadlineExceeded))
+	uploadCtx, _ = context.WithTimeoutCause(uploadCtx, time.Minute*5, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer cnclFn(errors.WithStack(context.Canceled))
 
 	// Only upload if the blob doesn't exist
diff --git a/cache/remotecache/azblob/utils.go b/cache/remotecache/azblob/utils.go
index 102aa7939..7b4f400ea 100644
--- a/cache/remotecache/azblob/utils.go
+++ b/cache/remotecache/azblob/utils.go
@@ -138,7 +138,7 @@ func createContainerClient(ctx context.Context, config *Config) (*container.Clie
 	}
 
 	ctx, cnclFn := context.WithCancelCause(ctx)
-	ctx, _ = context.WithTimeoutCause(ctx, time.Second*60, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, time.Second*60, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer cnclFn(errors.WithStack(context.Canceled))
 
 	containerClient := client.ServiceClient().NewContainerClient(config.Container)
@@ -150,7 +150,7 @@ func createContainerClient(ctx context.Context, config *Config) (*container.Clie
 
 	if bloberror.HasCode(err, bloberror.ContainerNotFound) {
 		ctx, cnclFn := context.WithCancelCause(ctx)
-		ctx, _ = context.WithTimeoutCause(ctx, time.Minute*5, errors.WithStack(context.DeadlineExceeded))
+		ctx, _ = context.WithTimeoutCause(ctx, time.Minute*5, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 		defer cnclFn(errors.WithStack(context.Canceled))
 		_, err := containerClient.Create(ctx, &container.CreateOptions{})
 		if err != nil {
@@ -175,7 +175,7 @@ func blobKey(config *Config, digest digest.Digest) string {
 func blobExists(ctx context.Context, containerClient *container.Client, blobKey string) (bool, error) {
 	blobClient := containerClient.NewBlobClient(blobKey)
 	ctx, cnclFn := context.WithCancelCause(ctx)
-	ctx, _ = context.WithTimeoutCause(ctx, time.Second*60, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, time.Second*60, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer cnclFn(errors.WithStack(context.Canceled))
 	_, err := blobClient.GetProperties(ctx, &blob.GetPropertiesOptions{})
 	if err == nil {
diff --git a/cache/remotecache/import.go b/cache/remotecache/import.go
index e8fff77c5..ff2aa0204 100644
--- a/cache/remotecache/import.go
+++ b/cache/remotecache/import.go
@@ -137,7 +137,7 @@ func readBlob(ctx context.Context, provider content.Provider, desc ocispecs.Desc
 	if err != nil {
 		// NOTE: even if err == EOF, we might have got expected dt here.
 		// For instance, http.Response.Body is known to return non-zero bytes with EOF.
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			if dtDigest := desc.Digest.Algorithm().FromBytes(dt); dtDigest != desc.Digest {
 				err = errors.Wrapf(err, "got EOF, expected %s (%d bytes), got %s (%d bytes)",
 					desc.Digest, desc.Size, dtDigest, len(dt))
diff --git a/cache/remotecache/local/local.go b/cache/remotecache/local/local.go
index 1a7223f8f..700240e30 100644
--- a/cache/remotecache/local/local.go
+++ b/cache/remotecache/local/local.go
@@ -106,7 +106,7 @@ func getContentStore(ctx context.Context, sm *session.Manager, g session.Group,
 		return nil, errors.New("local cache exporter/importer requires session")
 	}
 	timeoutCtx, cancel := context.WithCancelCause(ctx)
-	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	caller, err := sm.Get(timeoutCtx, sessionID, false)
diff --git a/cache/remotecache/s3/s3.go b/cache/remotecache/s3/s3.go
index 0114a508a..d1026bce9 100644
--- a/cache/remotecache/s3/s3.go
+++ b/cache/remotecache/s3/s3.go
@@ -16,7 +16,6 @@ import (
 	"github.com/aws/aws-sdk-go-v2/credentials"
 	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
 	"github.com/aws/aws-sdk-go-v2/service/s3"
-	"github.com/aws/aws-sdk-go-v2/service/s3/types"
 	s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
 	"github.com/containerd/containerd/v2/core/content"
 	"github.com/containerd/containerd/v2/pkg/labels"
@@ -546,7 +545,7 @@ func (s3Client *s3Client) touch(ctx context.Context, key string, size *int64) (e
 
 	var currentPartNumber int32 = 1
 	var currentPosition int64
-	var completedParts []types.CompletedPart
+	var completedParts []s3types.CompletedPart
 
 	for currentPosition < *size {
 		copyRange := buildCopySourceRange(currentPosition, *size)
@@ -564,7 +563,7 @@ func (s3Client *s3Client) touch(ctx context.Context, key string, size *int64) (e
 		}
 		partNumber := new(int32)
 		*partNumber = currentPartNumber
-		completedParts = append(completedParts, types.CompletedPart{
+		completedParts = append(completedParts, s3types.CompletedPart{
 			ETag:       uploadPartCopyResult.CopyPartResult.ETag,
 			PartNumber: partNumber,
 		})
@@ -577,7 +576,7 @@ func (s3Client *s3Client) touch(ctx context.Context, key string, size *int64) (e
 		Bucket:   &s3Client.bucket,
 		Key:      &key,
 		UploadId: output.UploadId,
-		MultipartUpload: &types.CompletedMultipartUpload{
+		MultipartUpload: &s3types.CompletedMultipartUpload{
 			Parts: completedParts,
 		},
 	}
diff --git a/cache/remotecache/v1/chains.go b/cache/remotecache/v1/chains.go
index 2d05b9912..ca318ba22 100644
--- a/cache/remotecache/v1/chains.go
+++ b/cache/remotecache/v1/chains.go
@@ -226,10 +226,7 @@ func (c *item) LinkFrom(rec solver.CacheExporterRecord, index int, selector stri
 		return
 	}
 
-	for {
-		if index < len(c.links) {
-			break
-		}
+	for index >= len(c.links) {
 		c.links = append(c.links, map[link]struct{}{})
 	}
 
diff --git a/cache/util/fsutil.go b/cache/util/fsutil.go
index 34ee0c699..3fefd3385 100644
--- a/cache/util/fsutil.go
+++ b/cache/util/fsutil.go
@@ -62,7 +62,8 @@ func ReadFile(ctx context.Context, mount snapshot.Mountable, req ReadRequest) ([
 			// The filename here is internal to the mount, so we can restore
 			// the request base path for error reporting.
 			// See os.DirFS.Open for details.
-			if pe, ok := err.(*os.PathError); ok {
+			pe := &os.PathError{}
+			if errors.As(err, &pe) {
 				pe.Path = req.Filename
 			}
 			return errors.WithStack(err)
diff --git a/client/llb/definition.go b/client/llb/definition.go
index 3c9ee7320..73c8097ab 100644
--- a/client/llb/definition.go
+++ b/client/llb/definition.go
@@ -240,7 +240,7 @@ func (d *DefinitionOp) Inputs() []Output {
 		d.mu.Unlock()
 
 		inputs = append(inputs, &output{vertex: vtx, platform: platform, getIndex: func() (pb.OutputIndex, error) {
-			return pb.OutputIndex(vtx.index), nil
+			return vtx.index, nil
 		}})
 	}
 
diff --git a/client/llb/source.go b/client/llb/source.go
index 443a0cc6b..cb1f47206 100644
--- a/client/llb/source.go
+++ b/client/llb/source.go
@@ -136,7 +136,7 @@ func Image(ref string, opts ...ImageOption) State {
 	} else if info.metaResolver != nil {
 		if _, ok := r.(reference.Digested); ok || !info.resolveDigest {
 			return NewState(src.Output()).Async(func(ctx context.Context, st State, c *Constraints) (State, error) {
-				p := info.Constraints.Platform
+				p := info.Platform
 				if p == nil {
 					p = c.Platform
 				}
@@ -153,7 +153,7 @@ func Image(ref string, opts ...ImageOption) State {
 			})
 		}
 		return Scratch().Async(func(ctx context.Context, _ State, c *Constraints) (State, error) {
-			p := info.Constraints.Platform
+			p := info.Platform
 			if p == nil {
 				p = c.Platform
 			}
diff --git a/client/prune.go b/client/prune.go
index 1d6d02df0..0b4ea2706 100644
--- a/client/prune.go
+++ b/client/prune.go
@@ -18,9 +18,9 @@ func (c *Client) Prune(ctx context.Context, ch chan UsageInfo, opts ...PruneOpti
 	req := &controlapi.PruneRequest{
 		Filter:        info.Filter,
 		KeepDuration:  int64(info.KeepDuration),
-		ReservedSpace: int64(info.ReservedSpace),
-		MaxUsedSpace:  int64(info.MaxUsedSpace),
-		MinFreeSpace:  int64(info.MinFreeSpace),
+		ReservedSpace: info.ReservedSpace,
+		MaxUsedSpace:  info.MaxUsedSpace,
+		MinFreeSpace:  info.MinFreeSpace,
 	}
 	if info.All {
 		req.All = true
@@ -33,7 +33,7 @@ func (c *Client) Prune(ctx context.Context, ch chan UsageInfo, opts ...PruneOpti
 	for {
 		d, err := cl.Recv()
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				return nil
 			}
 			return err
diff --git a/client/solve.go b/client/solve.go
index f3e97b3aa..d9a177fd6 100644
--- a/client/solve.go
+++ b/client/solve.go
@@ -322,7 +322,7 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
 		for {
 			resp, err := stream.Recv()
 			if err != nil {
-				if err == io.EOF {
+				if errors.Is(err, io.EOF) {
 					return nil
 				}
 				return errors.Wrap(err, "failed to receive status")
@@ -356,7 +356,7 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
 			return nil, err
 		}
 		var manifestDesc ocispecs.Descriptor
-		if err = json.Unmarshal([]byte(manifestDescDt), &manifestDesc); err != nil {
+		if err = json.Unmarshal(manifestDescDt, &manifestDesc); err != nil {
 			return nil, err
 		}
 		for _, storePath := range storesToUpdate {
diff --git a/cmd/buildctl/common/common.go b/cmd/buildctl/common/common.go
index 05a77782e..346ef5e2c 100644
--- a/cmd/buildctl/common/common.go
+++ b/cmd/buildctl/common/common.go
@@ -71,10 +71,10 @@ func ResolveClient(c *cli.Context) (*client.Client, error) {
 		opts = append(opts, client.WithCredentials(cert, key))
 	}
 
-	timeout := time.Duration(c.GlobalInt("timeout"))
+	timeout := time.Duration(c.GlobalInt("timeout")) * time.Second
 	if timeout > 0 {
 		ctx2, cancel := context.WithCancelCause(ctx)
-		ctx2, _ = context.WithTimeoutCause(ctx2, timeout*time.Second, errors.WithStack(context.DeadlineExceeded))
+		ctx2, _ = context.WithTimeoutCause(ctx2, timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 		ctx = ctx2
 		defer func() { cancel(errors.WithStack(context.Canceled)) }()
 	}
diff --git a/cmd/buildctl/common/trace.go b/cmd/buildctl/common/trace.go
index c62576dc8..47e6ad5e9 100644
--- a/cmd/buildctl/common/trace.go
+++ b/cmd/buildctl/common/trace.go
@@ -41,6 +41,7 @@ func AttachAppContext(app *cli.App) error {
 					}
 				}
 
+				ctx := ctx
 				ctx, span = tracer.Start(ctx, name, trace.WithAttributes(
 					attribute.StringSlice("command", os.Args),
 				))
diff --git a/cmd/buildctl/debug/logs.go b/cmd/buildctl/debug/logs.go
index a014c2d7d..d3db9730a 100644
--- a/cmd/buildctl/debug/logs.go
+++ b/cmd/buildctl/debug/logs.go
@@ -57,7 +57,7 @@ func logs(clicontext *cli.Context) error {
 		}
 		he, err := cl.Recv()
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				return errors.Errorf("ref %s not found", ref)
 			}
 			return err
diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go
index 1c5d9293b..d3bf198d8 100644
--- a/cmd/buildkitd/main.go
+++ b/cmd/buildkitd/main.go
@@ -610,7 +610,7 @@ func applyMainFlags(c *cli.Context, cfg *config.Config) error {
 			}
 			cfg.GRPC.SecurityDescriptor = secDescriptor
 		} else {
-			gid, err := groupToGid(group)
+			gid, err := groupToGID(group)
 			if err != nil {
 				return err
 			}
@@ -646,22 +646,17 @@ func applyMainFlags(c *cli.Context, cfg *config.Config) error {
 }
 
 // Convert a string containing either a group name or a stringified gid into a numeric id)
-func groupToGid(group string) (int, error) {
+func groupToGID(group string) (int, error) {
 	if group == "" {
 		return os.Getgid(), nil
 	}
 
-	var (
-		err error
-		id  int
-	)
-
 	// Try and parse as a number, if the error is ErrSyntax
 	// (i.e. its not a number) then we carry on and try it as a
 	// name.
-	if id, err = strconv.Atoi(group); err == nil {
+	if id, err := strconv.Atoi(group); err == nil {
 		return id, nil
-	} else if err.(*strconv.NumError).Err != strconv.ErrSyntax {
+	} else if !errors.Is(err, strconv.ErrSyntax) {
 		return 0, err
 	}
 
@@ -671,11 +666,7 @@ func groupToGid(group string) (int, error) {
 	}
 	group = ginfo.Gid
 
-	if id, err = strconv.Atoi(group); err != nil {
-		return 0, err
-	}
-
-	return id, nil
+	return strconv.Atoi(group)
 }
 
 func getListener(addr string, uid, gid int, secDescriptor string, tlsConfig *tls.Config, warnTLS bool) (net.Listener, error) {
diff --git a/cmd/buildkitd/main_containerd_worker.go b/cmd/buildkitd/main_containerd_worker.go
index 38f0844bb..d718fa91d 100644
--- a/cmd/buildkitd/main_containerd_worker.go
+++ b/cmd/buildkitd/main_containerd_worker.go
@@ -94,22 +94,22 @@ func init() {
 		cli.StringFlag{
 			Name:  "containerd-worker-net",
 			Usage: "worker network type (auto, bridge, cni or host)",
-			Value: defaultConf.Workers.Containerd.NetworkConfig.Mode,
+			Value: defaultConf.Workers.Containerd.Mode,
 		},
 		cli.StringFlag{
 			Name:  "containerd-cni-config-path",
 			Usage: "path of cni config file",
-			Value: defaultConf.Workers.Containerd.NetworkConfig.CNIConfigPath,
+			Value: defaultConf.Workers.Containerd.CNIConfigPath,
 		},
 		cli.StringFlag{
 			Name:  "containerd-cni-binary-dir",
 			Usage: "path of cni binary files",
-			Value: defaultConf.Workers.Containerd.NetworkConfig.CNIBinaryPath,
+			Value: defaultConf.Workers.Containerd.CNIBinaryPath,
 		},
 		cli.IntFlag{
 			Name:  "containerd-cni-pool-size",
 			Usage: "size of cni network namespace pool",
-			Value: defaultConf.Workers.Containerd.NetworkConfig.CNIPoolSize,
+			Value: defaultConf.Workers.Containerd.CNIPoolSize,
 		},
 		cli.StringFlag{
 			Name:  "containerd-worker-snapshotter",
@@ -238,16 +238,16 @@ func applyContainerdFlags(c *cli.Context, cfg *config.Config) error {
 	}
 
 	if c.GlobalIsSet("containerd-worker-net") {
-		cfg.Workers.Containerd.NetworkConfig.Mode = c.GlobalString("containerd-worker-net")
+		cfg.Workers.Containerd.Mode = c.GlobalString("containerd-worker-net")
 	}
 	if c.GlobalIsSet("containerd-cni-config-path") {
-		cfg.Workers.Containerd.NetworkConfig.CNIConfigPath = c.GlobalString("containerd-cni-config-path")
+		cfg.Workers.Containerd.CNIConfigPath = c.GlobalString("containerd-cni-config-path")
 	}
 	if c.GlobalIsSet("containerd-cni-pool-size") {
-		cfg.Workers.Containerd.NetworkConfig.CNIPoolSize = c.GlobalInt("containerd-cni-pool-size")
+		cfg.Workers.Containerd.CNIPoolSize = c.GlobalInt("containerd-cni-pool-size")
 	}
 	if c.GlobalIsSet("containerd-cni-binary-dir") {
-		cfg.Workers.Containerd.NetworkConfig.CNIBinaryPath = c.GlobalString("containerd-cni-binary-dir")
+		cfg.Workers.Containerd.CNIBinaryPath = c.GlobalString("containerd-cni-binary-dir")
 	}
 	if c.GlobalIsSet("containerd-worker-snapshotter") {
 		cfg.Workers.Containerd.Snapshotter = c.GlobalString("containerd-worker-snapshotter")
@@ -275,8 +275,8 @@ func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([
 
 	if cfg.Rootless {
 		bklog.L.Debugf("running in rootless mode")
-		if common.config.Workers.Containerd.NetworkConfig.Mode == "auto" {
-			common.config.Workers.Containerd.NetworkConfig.Mode = "host"
+		if common.config.Workers.Containerd.Mode == "auto" {
+			common.config.Workers.Containerd.Mode = "host"
 		}
 	}
 
@@ -288,7 +288,7 @@ func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([
 	}
 
 	nc := netproviders.Opt{
-		Mode: common.config.Workers.Containerd.NetworkConfig.Mode,
+		Mode: common.config.Workers.Containerd.Mode,
 		CNI: cniprovider.Opt{
 			Root:         common.config.Root,
 			ConfigPath:   common.config.Workers.Containerd.CNIConfigPath,
diff --git a/cmd/buildkitd/main_oci_worker.go b/cmd/buildkitd/main_oci_worker.go
index f31c5a04a..f50a9f461 100644
--- a/cmd/buildkitd/main_oci_worker.go
+++ b/cmd/buildkitd/main_oci_worker.go
@@ -91,22 +91,22 @@ func init() {
 		cli.StringFlag{
 			Name:  "oci-worker-net",
 			Usage: "worker network type (auto, bridge, cni or host)",
-			Value: defaultConf.Workers.OCI.NetworkConfig.Mode,
+			Value: defaultConf.Workers.OCI.Mode,
 		},
 		cli.StringFlag{
 			Name:  "oci-cni-config-path",
 			Usage: "path of cni config file",
-			Value: defaultConf.Workers.OCI.NetworkConfig.CNIConfigPath,
+			Value: defaultConf.Workers.OCI.CNIConfigPath,
 		},
 		cli.StringFlag{
 			Name:  "oci-cni-binary-dir",
 			Usage: "path of cni binary files",
-			Value: defaultConf.Workers.OCI.NetworkConfig.CNIBinaryPath,
+			Value: defaultConf.Workers.OCI.CNIBinaryPath,
 		},
 		cli.IntFlag{
 			Name:  "oci-cni-pool-size",
 			Usage: "size of cni network namespace pool",
-			Value: defaultConf.Workers.OCI.NetworkConfig.CNIPoolSize,
+			Value: defaultConf.Workers.OCI.CNIPoolSize,
 		},
 		cli.StringFlag{
 			Name:  "oci-worker-binary",
@@ -229,16 +229,16 @@ func applyOCIFlags(c *cli.Context, cfg *config.Config) error {
 	}
 
 	if c.GlobalIsSet("oci-worker-net") {
-		cfg.Workers.OCI.NetworkConfig.Mode = c.GlobalString("oci-worker-net")
+		cfg.Workers.OCI.Mode = c.GlobalString("oci-worker-net")
 	}
 	if c.GlobalIsSet("oci-cni-config-path") {
-		cfg.Workers.OCI.NetworkConfig.CNIConfigPath = c.GlobalString("oci-cni-worker-path")
+		cfg.Workers.OCI.CNIConfigPath = c.GlobalString("oci-cni-worker-path")
 	}
 	if c.GlobalIsSet("oci-cni-binary-dir") {
-		cfg.Workers.OCI.NetworkConfig.CNIBinaryPath = c.GlobalString("oci-cni-binary-dir")
+		cfg.Workers.OCI.CNIBinaryPath = c.GlobalString("oci-cni-binary-dir")
 	}
 	if c.GlobalIsSet("oci-cni-pool-size") {
-		cfg.Workers.OCI.NetworkConfig.CNIPoolSize = c.GlobalInt("oci-cni-pool-size")
+		cfg.Workers.OCI.CNIPoolSize = c.GlobalInt("oci-cni-pool-size")
 	}
 	if c.GlobalIsSet("oci-worker-binary") {
 		cfg.Workers.OCI.Binary = c.GlobalString("oci-worker-binary")
@@ -281,8 +281,8 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker
 
 	if cfg.Rootless {
 		bklog.L.Debugf("running in rootless mode")
-		if common.config.Workers.OCI.NetworkConfig.Mode == "auto" {
-			common.config.Workers.OCI.NetworkConfig.Mode = "host"
+		if common.config.Workers.OCI.Mode == "auto" {
+			common.config.Workers.OCI.Mode = "host"
 		}
 	}
 
@@ -303,7 +303,7 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker
 	}
 
 	nc := netproviders.Opt{
-		Mode: common.config.Workers.OCI.NetworkConfig.Mode,
+		Mode: common.config.Workers.OCI.Mode,
 		CNI: cniprovider.Opt{
 			Root:         common.config.Root,
 			ConfigPath:   common.config.Workers.OCI.CNIConfigPath,
diff --git a/control/gateway/gateway.go b/control/gateway/gateway.go
index 5b51d252f..572c9a607 100644
--- a/control/gateway/gateway.go
+++ b/control/gateway/gateway.go
@@ -60,7 +60,7 @@ func (gwf *GatewayForwarder) lookupForwarder(ctx context.Context) (gateway.LLBBr
 	}
 
 	ctx, cancel := context.WithCancelCause(ctx)
-	ctx, _ = context.WithTimeoutCause(ctx, 3*time.Second, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, 3*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	go func() {
diff --git a/docker-bake.hcl b/docker-bake.hcl
index 350fda4fc..82e4872fd 100644
--- a/docker-bake.hcl
+++ b/docker-bake.hcl
@@ -170,6 +170,7 @@ target "lint" {
   args = {
     TARGETNAME = buildtags.name
     BUILDTAGS = buildtags.tags
+    GOLANGCI_FROM_SOURCE = "true"
   }
   platforms = ( buildtags.target == "golangci-lint" || buildtags.name == "gopls" ) && GOLANGCI_LINT_MULTIPLATFORM != null ? [
     "freebsd/amd64",
diff --git a/errdefs/internal.go b/errdefs/internal.go
index 24cea7e33..bf03d0f99 100644
--- a/errdefs/internal.go
+++ b/errdefs/internal.go
@@ -5,13 +5,13 @@ import (
 	"syscall"
 )
 
-type internalErr struct {
+type internalError struct {
 	error
 }
 
-func (internalErr) System() {}
+func (internalError) System() {}
 
-func (err internalErr) Unwrap() error {
+func (err internalError) Unwrap() error {
 	return err.error
 }
 
@@ -19,13 +19,13 @@ type system interface {
 	System()
 }
 
-var _ system = internalErr{}
+var _ system = internalError{}
 
 func Internal(err error) error {
 	if err == nil {
 		return nil
 	}
-	return internalErr{err}
+	return internalError{err}
 }
 
 func IsInternal(err error) bool {
diff --git a/examples/build-using-dockerfile/main.go b/examples/build-using-dockerfile/main.go
index 3de7c60af..6c3b7b516 100644
--- a/examples/build-using-dockerfile/main.go
+++ b/examples/build-using-dockerfile/main.go
@@ -127,9 +127,10 @@ func action(clicontext *cli.Context) error {
 
 func newSolveOpt(clicontext *cli.Context, w io.WriteCloser) (*client.SolveOpt, error) {
 	buildCtx := clicontext.Args().First()
-	if buildCtx == "" {
+	switch buildCtx {
+	case "":
 		return nil, errors.New("please specify build context (e.g. \".\" for the current directory)")
-	} else if buildCtx == "-" {
+	case "-":
 		return nil, errors.New("stdin not supported yet")
 	}
 
diff --git a/executor/containerdexecutor/executor.go b/executor/containerdexecutor/executor.go
index 99540d7c6..9e248ad2b 100644
--- a/executor/containerdexecutor/executor.go
+++ b/executor/containerdexecutor/executor.go
@@ -399,7 +399,7 @@ func (w *containerdExecutor) runProcess(ctx context.Context, p ctd.Process, resi
 			ctxDone = nil
 			var killCtx context.Context
 			killCtx, cancel = context.WithCancelCause(context.Background())
-			killCtx, _ = context.WithTimeoutCause(killCtx, 10*time.Second, errors.WithStack(context.DeadlineExceeded))
+			killCtx, _ = context.WithTimeoutCause(killCtx, 10*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 			killCtxDone = killCtx.Done()
 			p.Kill(killCtx, syscall.SIGKILL)
 			io.Cancel()
diff --git a/executor/resources/sampler.go b/executor/resources/sampler.go
index 38e94812d..3e1e22282 100644
--- a/executor/resources/sampler.go
+++ b/executor/resources/sampler.go
@@ -122,7 +122,7 @@ func (s *Sampler[T]) run() {
 					ss.err = nil
 				}
 				dur := ss.last.Sub(ss.first)
-				if time.Duration(ss.interval)*time.Duration(s.maxSamples) <= dur {
+				if ss.interval*time.Duration(s.maxSamples) <= dur {
 					ss.interval *= 2
 				}
 			}
diff --git a/executor/runcexecutor/executor.go b/executor/runcexecutor/executor.go
index cbc3f9eba..f032a9d92 100644
--- a/executor/runcexecutor/executor.go
+++ b/executor/runcexecutor/executor.go
@@ -546,7 +546,7 @@ func (k procKiller) Kill(ctx context.Context) (err error) {
 	// this timeout is generally a no-op, the Kill ctx should already have a
 	// shorter timeout but here as a fail-safe for future refactoring.
 	ctx, cancel := context.WithCancelCause(ctx)
-	ctx, _ = context.WithTimeoutCause(ctx, 10*time.Second, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, 10*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	if k.pidfile == "" {
@@ -634,13 +634,13 @@ func runcProcessHandle(ctx context.Context, killer procKiller) (*procHandle, con
 		for {
 			select {
 			case <-ctx.Done():
-				killCtx, timeout := context.WithCancelCause(context.Background())
-				killCtx, _ = context.WithTimeoutCause(killCtx, 7*time.Second, errors.WithStack(context.DeadlineExceeded))
+				killCtx, timeout := context.WithCancelCause(context.Background())                                         //nolint:govet
+				killCtx, _ = context.WithTimeoutCause(killCtx, 7*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 				if err := p.killer.Kill(killCtx); err != nil {
 					select {
 					case <-killCtx.Done():
 						cancel(errors.WithStack(context.Cause(ctx)))
-						return
+						return //nolint:govet
 					default:
 					}
 				}
@@ -693,7 +693,7 @@ func (p *procHandle) WaitForReady(ctx context.Context) error {
 // callback is non-nil it will be called after receiving the pid.
 func (p *procHandle) WaitForStart(ctx context.Context, startedCh <-chan int, started func()) error {
 	ctx, cancel := context.WithCancelCause(ctx)
-	ctx, _ = context.WithTimeoutCause(ctx, 10*time.Second, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, 10*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 	select {
 	case <-ctx.Done():
diff --git a/executor/runcexecutor/executor_linux.go b/executor/runcexecutor/executor_linux.go
index 350075cdd..cd374b791 100644
--- a/executor/runcexecutor/executor_linux.go
+++ b/executor/runcexecutor/executor_linux.go
@@ -129,7 +129,7 @@ func (w *runcExecutor) callWithIO(ctx context.Context, process executor.ProcessI
 			if errors.As(err, &ptmClosedError) {
 				if ptmClosedError.Op == "read" &&
 					ptmClosedError.Path == "/dev/ptmx" &&
-					ptmClosedError.Err == syscall.EIO {
+					errors.Is(ptmClosedError.Err, syscall.EIO) {
 					return nil
 				}
 			}
diff --git a/executor/stubs.go b/executor/stubs.go
index 5ea4f5edd..d39be0fbe 100644
--- a/executor/stubs.go
+++ b/executor/stubs.go
@@ -33,7 +33,7 @@ func MountStubsCleaner(ctx context.Context, dir string, mounts []Mount, recursiv
 
 		for {
 			_, err = os.Lstat(realPath)
-			if !(errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR)) {
+			if !errors.Is(err, os.ErrNotExist) && !errors.Is(err, syscall.ENOTDIR) {
 				break
 			}
 			paths = append(paths, realPath)
diff --git a/exporter/local/export.go b/exporter/local/export.go
index 225503b3d..29c6afbac 100644
--- a/exporter/local/export.go
+++ b/exporter/local/export.go
@@ -80,7 +80,7 @@ func (e *localExporter) Config() *exporter.Config {
 
 func (e *localExporterInstance) Export(ctx context.Context, inp *exporter.Source, _ exptypes.InlineCache, sessionID string) (map[string]string, exporter.DescriptorReference, error) {
 	timeoutCtx, cancel := context.WithCancelCause(ctx)
-	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	if e.opts.Epoch == nil {
diff --git a/exporter/oci/export.go b/exporter/oci/export.go
index 3db1278fb..c1bee4e4c 100644
--- a/exporter/oci/export.go
+++ b/exporter/oci/export.go
@@ -217,7 +217,7 @@ func (e *imageExporterInstance) Export(ctx context.Context, src *exporter.Source
 	}
 
 	timeoutCtx, cancel := context.WithCancelCause(ctx)
-	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID, false)
diff --git a/exporter/tar/export.go b/exporter/tar/export.go
index 96eedffe8..770b38254 100644
--- a/exporter/tar/export.go
+++ b/exporter/tar/export.go
@@ -164,7 +164,7 @@ func (e *localExporterInstance) Export(ctx context.Context, inp *exporter.Source
 	}
 
 	timeoutCtx, cancel := context.WithCancelCause(ctx)
-	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID, false)
diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go
index ed5bccc0b..26b019df4 100644
--- a/frontend/dockerfile/builder/build.go
+++ b/frontend/dockerfile/builder/build.go
@@ -103,7 +103,7 @@ func Build(ctx context.Context, c client.Client) (_ *client.Result, err error) {
 	}
 
 	defer func() {
-		var el *parser.ErrorLocation
+		var el *parser.LocationError
 		if errors.As(err, &el) {
 			for _, l := range el.Locations {
 				err = wrapSource(err, src.SourceMap, l)
diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go
index 3d82e82a0..043ec22ed 100644
--- a/frontend/dockerfile/dockerfile2llb/convert.go
+++ b/frontend/dockerfile/dockerfile2llb/convert.go
@@ -137,7 +137,7 @@ func DockerfileLint(ctx context.Context, dt []byte, opt ConvertOpt) (*lint.LintR
 
 	_, err := toDispatchState(ctx, dt, opt)
 
-	var errLoc *parser.ErrorLocation
+	var errLoc *parser.LocationError
 	if err != nil {
 		buildErr := &lint.BuildError{
 			Message: err.Error(),
@@ -1218,7 +1218,7 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
 	// Run command can potentially access any file. Mark the full filesystem as used.
 	d.paths["/"] = struct{}{}
 
-	var args []string = c.CmdLine
+	var args = c.CmdLine
 	if len(c.Files) > 0 {
 		if len(args) != 1 || !c.PrependShell {
 			return errors.Errorf("parsing produced an invalid run command: %v", args)
@@ -1399,6 +1399,9 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
 			if user := d.image.Config.User; user != "" {
 				mkdirOpt = append(mkdirOpt, llb.WithUser(user))
 			}
+			if d.epoch != nil {
+				mkdirOpt = append(mkdirOpt, llb.WithCreatedTime(*d.epoch))
+			}
 			platform := opt.targetPlatform
 			if d.platform != nil {
 				platform = *d.platform
@@ -1704,7 +1707,7 @@ func dispatchOnbuild(d *dispatchState, c *instructions.OnbuildCommand) error {
 func dispatchCmd(d *dispatchState, c *instructions.CmdCommand, lint *linter.Linter) error {
 	validateUsedOnce(c, &d.cmd, lint)
 
-	var args []string = c.CmdLine
+	var args = c.CmdLine
 	if c.PrependShell {
 		if len(d.image.Config.Shell) == 0 {
 			msg := linter.RuleJSONArgsRecommended.Format(c.Name())
@@ -1720,7 +1723,7 @@ func dispatchCmd(d *dispatchState, c *instructions.CmdCommand, lint *linter.Lint
 func dispatchEntrypoint(d *dispatchState, c *instructions.EntrypointCommand, lint *linter.Linter) error {
 	validateUsedOnce(c, &d.entrypoint, lint)
 
-	var args []string = c.CmdLine
+	var args = c.CmdLine
 	if c.PrependShell {
 		if len(d.image.Config.Shell) == 0 {
 			msg := linter.RuleJSONArgsRecommended.Format(c.Name())
diff --git a/frontend/dockerfile/linter/linter.go b/frontend/dockerfile/linter/linter.go
index 890acc53b..405f6923d 100644
--- a/frontend/dockerfile/linter/linter.go
+++ b/frontend/dockerfile/linter/linter.go
@@ -55,7 +55,7 @@ func (lc *Linter) Run(rule LinterRuleI, location []parser.Range, txt ...string)
 	rulename := rule.RuleName()
 	if rule.IsExperimental() {
 		_, experimentalOk := lc.ExperimentalRules[rulename]
-		if !(lc.ExperimentalAll || experimentalOk) {
+		if !lc.ExperimentalAll && !experimentalOk {
 			return
 		}
 	} else {
diff --git a/frontend/dockerfile/parser/errors.go b/frontend/dockerfile/parser/errors.go
index 08a40c5d4..b3bcf2ae8 100644
--- a/frontend/dockerfile/parser/errors.go
+++ b/frontend/dockerfile/parser/errors.go
@@ -5,14 +5,14 @@ import (
 	"github.com/pkg/errors"
 )
 
-// ErrorLocation gives a location in source code that caused the error
-type ErrorLocation struct {
+// LocationError gives a location in source code that caused the error
+type LocationError struct {
 	Locations [][]Range
 	error
 }
 
 // Unwrap unwraps to the next error
-func (e *ErrorLocation) Unwrap() error {
+func (e *LocationError) Unwrap() error {
 	return e.error
 }
 
@@ -45,7 +45,7 @@ func setLocation(err error, location []Range, add bool) error {
 	if err == nil {
 		return nil
 	}
-	var el *ErrorLocation
+	var el *LocationError
 	if errors.As(err, &el) {
 		if add {
 			el.Locations = append(el.Locations, location)
@@ -54,7 +54,7 @@ func setLocation(err error, location []Range, add bool) error {
 		}
 		return err
 	}
-	return stack.Enable(&ErrorLocation{
+	return stack.Enable(&LocationError{
 		error:     err,
 		Locations: [][]Range{location},
 	})
diff --git a/frontend/dockerfile/parser/line_parsers.go b/frontend/dockerfile/parser/line_parsers.go
index 104978164..eb86e73b4 100644
--- a/frontend/dockerfile/parser/line_parsers.go
+++ b/frontend/dockerfile/parser/line_parsers.go
@@ -318,7 +318,7 @@ func parseMaybeJSON(rest string, d *directives) (*Node, map[string]bool, error)
 	if err == nil {
 		return node, attrs, nil
 	}
-	if err == errDockerfileNotStringArray {
+	if errors.Is(err, errDockerfileNotStringArray) {
 		return nil, nil, err
 	}
 
@@ -336,7 +336,7 @@ func parseMaybeJSONToList(rest string, d *directives) (*Node, map[string]bool, e
 	if err == nil {
 		return node, attrs, nil
 	}
-	if err == errDockerfileNotStringArray {
+	if errors.Is(err, errDockerfileNotStringArray) {
 		return nil, nil, err
 	}
 
diff --git a/frontend/dockerfile/parser/parser.go b/frontend/dockerfile/parser/parser.go
index f1667a108..caabe4dc2 100644
--- a/frontend/dockerfile/parser/parser.go
+++ b/frontend/dockerfile/parser/parser.go
@@ -556,8 +556,8 @@ func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
 }
 
 func handleScannerError(err error) error {
-	switch err {
-	case bufio.ErrTooLong:
+	switch {
+	case errors.Is(err, bufio.ErrTooLong):
 		return errors.Errorf("dockerfile line greater than max allowed size of %d", bufio.MaxScanTokenSize-1)
 	default:
 		return err
diff --git a/frontend/gateway/container/container.go b/frontend/gateway/container/container.go
index 596a41ac3..59b447b00 100644
--- a/frontend/gateway/container/container.go
+++ b/frontend/gateway/container/container.go
@@ -21,10 +21,8 @@ import (
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/snapshot"
 	"github.com/moby/buildkit/solver/llbsolver/mounts"
-	"github.com/moby/buildkit/solver/pb"
 	opspb "github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/stack"
-	utilsystem "github.com/moby/buildkit/util/system"
 	"github.com/moby/buildkit/worker"
 	"github.com/pkg/errors"
 	"golang.org/x/sync/errgroup"
@@ -80,9 +78,9 @@ func NewContainer(ctx context.Context, cm cache.Manager, exec executor.Executor,
 		mnts = append(mnts, m.Mount)
 		if m.WorkerRef != nil {
 			refs = append(refs, m.WorkerRef)
-			m.Mount.Input = int64(len(refs) - 1)
+			m.Input = int64(len(refs) - 1)
 		} else {
-			m.Mount.Input = int64(opspb.Empty)
+			m.Input = int64(opspb.Empty)
 		}
 	}
 
@@ -328,7 +326,7 @@ func (gwCtr *gatewayContainer) Start(ctx context.Context, req client.StartReques
 	if procInfo.Meta.Cwd == "" {
 		procInfo.Meta.Cwd = "/"
 	}
-	procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "PATH", utilsystem.DefaultPathEnv(gwCtr.platform.OS))
+	procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "PATH", system.DefaultPathEnv(gwCtr.platform.OS))
 	if req.Tty {
 		procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "TERM", "xterm")
 	}
@@ -378,7 +376,7 @@ func (gwCtr *gatewayContainer) Start(ctx context.Context, req client.StartReques
 	return gwProc, nil
 }
 
-func (gwCtr *gatewayContainer) loadSecretEnv(ctx context.Context, secretEnv []*pb.SecretEnv) ([]string, error) {
+func (gwCtr *gatewayContainer) loadSecretEnv(ctx context.Context, secretEnv []*opspb.SecretEnv) ([]string, error) {
 	out := make([]string, 0, len(secretEnv))
 	for _, sopt := range secretEnv {
 		id := sopt.ID
@@ -394,7 +392,7 @@ func (gwCtr *gatewayContainer) loadSecretEnv(ctx context.Context, secretEnv []*p
 			}
 			return nil
 		})
-		if err != nil && !(errors.Is(err, secrets.ErrNotFound) && sopt.Optional) {
+		if err != nil && (!errors.Is(err, secrets.ErrNotFound) || !sopt.Optional) {
 			return nil, err
 		}
 		out = append(out, fmt.Sprintf("%s=%s", sopt.Name, string(dt)))
diff --git a/frontend/gateway/forwarder/forward.go b/frontend/gateway/forwarder/forward.go
index eeb984fb3..4180896a1 100644
--- a/frontend/gateway/forwarder/forward.go
+++ b/frontend/gateway/forwarder/forward.go
@@ -59,15 +59,7 @@ type BridgeClient struct {
 }
 
 func (c *BridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) {
-	res, err := c.FrontendLLBBridge.Solve(ctx, frontend.SolveRequest{
-		Evaluate:       req.Evaluate,
-		Definition:     req.Definition,
-		Frontend:       req.Frontend,
-		FrontendOpt:    req.FrontendOpt,
-		FrontendInputs: req.FrontendInputs,
-		CacheImports:   req.CacheImports,
-		SourcePolicies: req.SourcePolicies,
-	}, c.sid)
+	res, err := c.FrontendLLBBridge.Solve(ctx, req, c.sid)
 	if err != nil {
 		return nil, c.wrapSolveError(err)
 	}
diff --git a/frontend/gateway/gateway.go b/frontend/gateway/gateway.go
index fc06f95e8..a42fc617e 100644
--- a/frontend/gateway/gateway.go
+++ b/frontend/gateway/gateway.go
@@ -1572,7 +1572,7 @@ func (lbf *llbBridgeForwarder) ExecProcess(srv pb.LLBBridge_ExecProcessServer) e
 						}()
 						dest := &outputWriter{
 							stream:    srv,
-							fd:        uint32(fd),
+							fd:        fd,
 							processID: pid,
 						}
 						_, err := io.Copy(dest, file)
@@ -1586,7 +1586,7 @@ func (lbf *llbBridgeForwarder) ExecProcess(srv pb.LLBBridge_ExecProcessServer) e
 							ProcessID: pid,
 							Input: &pb.ExecMessage_File{
 								File: &pb.FdMessage{
-									Fd:  uint32(fd),
+									Fd:  fd,
 									EOF: true,
 								},
 							},
diff --git a/frontend/gateway/grpcclient/client.go b/frontend/gateway/grpcclient/client.go
index 615700f51..93fee1262 100644
--- a/frontend/gateway/grpcclient/client.go
+++ b/frontend/gateway/grpcclient/client.go
@@ -44,7 +44,7 @@ type GrpcClient interface {
 
 func New(ctx context.Context, opts map[string]string, session, product string, c pb.LLBBridgeClient, w []client.WorkerInfo) (GrpcClient, error) {
 	pingCtx, pingCancel := context.WithCancelCause(ctx)
-	pingCtx, _ = context.WithTimeoutCause(pingCtx, 15*time.Second, errors.WithStack(context.DeadlineExceeded))
+	pingCtx, _ = context.WithTimeoutCause(pingCtx, 15*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer pingCancel(errors.WithStack(context.Canceled))
 	resp, err := c.Ping(pingCtx, &pb.PingRequest{})
 	if err != nil {
diff --git a/frontend/gateway/pb/caps.go b/frontend/gateway/pb/caps.go
index 006aeee2e..7e43259e2 100644
--- a/frontend/gateway/pb/caps.go
+++ b/frontend/gateway/pb/caps.go
@@ -1,4 +1,4 @@
-package moby_buildkit_v1_frontend //nolint:revive
+package moby_buildkit_v1_frontend //nolint:revive,staticcheck
 
 import "github.com/moby/buildkit/util/apicaps"
 
diff --git a/frontend/gateway/pb/exit.go b/frontend/gateway/pb/exit.go
index d978bfa66..57007185c 100644
--- a/frontend/gateway/pb/exit.go
+++ b/frontend/gateway/pb/exit.go
@@ -1,4 +1,4 @@
-package moby_buildkit_v1_frontend //nolint:revive
+package moby_buildkit_v1_frontend //nolint:revive,staticcheck
 
 import (
 	"fmt"
diff --git a/hack/dockerfiles/lint.Dockerfile b/hack/dockerfiles/lint.Dockerfile
index 627e6f569..fd56140fe 100644
--- a/hack/dockerfiles/lint.Dockerfile
+++ b/hack/dockerfiles/lint.Dockerfile
@@ -4,7 +4,7 @@ ARG GO_VERSION=1.23
 ARG ALPINE_VERSION=3.21
 ARG XX_VERSION=1.6.1
 ARG PROTOLINT_VERSION=0.50.5
-ARG GOLANGCI_LINT_VERSION=v1.61.0
+ARG GOLANGCI_LINT_VERSION=v2.1.5
 ARG GOLANGCI_FROM_SOURCE=false
 # v0.31 requires go1.24
 ARG GOPLS_VERSION=v0.30.0
diff --git a/session/auth/authprovider/authprovider.go b/session/auth/authprovider/authprovider.go
index 54e458e53..88fe7d02b 100644
--- a/session/auth/authprovider/authprovider.go
+++ b/session/auth/authprovider/authprovider.go
@@ -8,6 +8,7 @@ import (
 	"crypto/tls"
 	"crypto/x509"
 	"fmt"
+	"net/http"
 	"os"
 	"runtime"
 	"strconv"
@@ -20,7 +21,7 @@ import (
 	"github.com/docker/cli/cli/config"
 	"github.com/docker/cli/cli/config/configfile"
 	"github.com/docker/cli/cli/config/types"
-	http "github.com/hashicorp/go-cleanhttp"
+	cleanhttp "github.com/hashicorp/go-cleanhttp"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/session/auth"
 	"github.com/moby/buildkit/util/progress/progresswriter"
@@ -125,7 +126,7 @@ func (ap *authProvider) FetchToken(ctx context.Context, req *auth.FetchTokenRequ
 
 	httpClient := tracing.DefaultClient
 	if tc, err := ap.tlsConfig(req.Host); err == nil && tc != nil {
-		transport := http.DefaultTransport()
+		transport := cleanhttp.DefaultTransport()
 		transport.TLSClientConfig = tc
 		httpClient.Transport = tracing.NewTransport(transport)
 	}
@@ -151,7 +152,7 @@ func (ap *authProvider) FetchToken(ctx context.Context, req *auth.FetchTokenRequ
 				// Registries without support for POST may return 404 for POST /v2/token.
 				// As of September 2017, GCR is known to return 404.
 				// As of February 2018, JFrog Artifactory is known to return 401.
-				if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
+				if (errStatus.StatusCode == http.StatusMethodNotAllowed && to.Username != "") || errStatus.StatusCode == http.StatusNotFound || errStatus.StatusCode == http.StatusUnauthorized {
 					resp, err := authutil.FetchToken(ctx, httpClient, nil, to)
 					if err != nil {
 						return nil, err
diff --git a/session/filesync/diffcopy.go b/session/filesync/diffcopy.go
index 5176b5c03..5e8b40b93 100644
--- a/session/filesync/diffcopy.go
+++ b/session/filesync/diffcopy.go
@@ -32,7 +32,7 @@ type bufferedWriteCloser struct {
 }
 
 func (bwc *bufferedWriteCloser) Close() error {
-	if err := bwc.Writer.Flush(); err != nil {
+	if err := bwc.Flush(); err != nil {
 		return errors.WithStack(err)
 	}
 	return bwc.Closer.Close()
@@ -59,10 +59,10 @@ func (wc *streamWriterCloser) Write(dt []byte) (int, error) {
 		return n1 + n2, nil
 	}
 
-	if err := wc.ClientStream.SendMsg(&BytesMessage{Data: dt}); err != nil {
+	if err := wc.SendMsg(&BytesMessage{Data: dt}); err != nil {
 		// SendMsg return EOF on remote errors
 		if errors.Is(err, io.EOF) {
-			if err := errors.WithStack(wc.ClientStream.RecvMsg(struct{}{})); err != nil {
+			if err := errors.WithStack(wc.RecvMsg(struct{}{})); err != nil {
 				return 0, err
 			}
 		}
@@ -72,12 +72,12 @@ func (wc *streamWriterCloser) Write(dt []byte) (int, error) {
 }
 
 func (wc *streamWriterCloser) Close() error {
-	if err := wc.ClientStream.CloseSend(); err != nil {
+	if err := wc.CloseSend(); err != nil {
 		return errors.WithStack(err)
 	}
 	// block until receiver is done
 	var bm BytesMessage
-	if err := wc.ClientStream.RecvMsg(&bm); err != io.EOF {
+	if err := wc.RecvMsg(&bm); !errors.Is(err, io.EOF) {
 		return errors.WithStack(err)
 	}
 	return nil
diff --git a/session/group.go b/session/group.go
index 66d18fcc7..14e02eb7b 100644
--- a/session/group.go
+++ b/session/group.go
@@ -73,7 +73,7 @@ func (sm *Manager) Any(ctx context.Context, g Group, f func(context.Context, str
 		}
 
 		timeoutCtx, cancel := context.WithCancelCause(ctx)
-		timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+		timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 		defer func() { cancel(errors.WithStack(context.Canceled)) }()
 		c, err := sm.Get(timeoutCtx, id, false)
 		if err != nil {
diff --git a/session/grpc.go b/session/grpc.go
index c207e5dde..d177fd54e 100644
--- a/session/grpc.go
+++ b/session/grpc.go
@@ -94,7 +94,7 @@ func monitorHealth(ctx context.Context, cc *grpc.ClientConn, cancelConn func(err
 			timeout := time.Duration(math.Max(float64(defaultHealthcheckDuration), float64(lastHealthcheckDuration)*1.5))
 
 			ctx, cancel := context.WithCancelCause(ctx)
-			ctx, _ = context.WithTimeoutCause(ctx, timeout, errors.WithStack(context.DeadlineExceeded))
+			ctx, _ = context.WithTimeoutCause(ctx, timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 			_, err := healthClient.Check(ctx, &grpc_health_v1.HealthCheckRequest{})
 			cancel(errors.WithStack(context.Canceled))
 
diff --git a/session/grpchijack/dial.go b/session/grpchijack/dial.go
index 019c2bbfe..39d78be0d 100644
--- a/session/grpchijack/dial.go
+++ b/session/grpchijack/dial.go
@@ -2,6 +2,7 @@ package grpchijack
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net"
 	"strings"
@@ -112,7 +113,7 @@ func (c *conn) Close() (err error) {
 			m.Data = c.buf
 			err = c.stream.RecvMsg(m)
 			if err != nil {
-				if err != io.EOF {
+				if !errors.Is(err, io.EOF) {
 					c.readMu.Unlock()
 					return
 				}
diff --git a/session/sshforward/copy.go b/session/sshforward/copy.go
index 902063c5d..506236cd6 100644
--- a/session/sshforward/copy.go
+++ b/session/sshforward/copy.go
@@ -21,7 +21,7 @@ func Copy(ctx context.Context, conn io.ReadWriteCloser, stream Stream, closeStre
 		p := &BytesMessage{}
 		for {
 			if err := stream.RecvMsg(p); err != nil {
-				if err == io.EOF {
+				if errors.Is(err, io.EOF) {
 					// indicates client performed CloseSend, but they may still be
 					// reading data
 					if closeWriter, ok := conn.(interface {
@@ -55,7 +55,7 @@ func Copy(ctx context.Context, conn io.ReadWriteCloser, stream Stream, closeStre
 			buf := make([]byte, 32*1024)
 			n, err := conn.Read(buf)
 			switch {
-			case err == io.EOF:
+			case errors.Is(err, io.EOF):
 				if closeStream != nil {
 					closeStream()
 				}
diff --git a/session/sshforward/ssh.go b/session/sshforward/ssh.go
index 8a041b311..7cd257bc3 100644
--- a/session/sshforward/ssh.go
+++ b/session/sshforward/ssh.go
@@ -40,7 +40,7 @@ func (s *server) run(ctx context.Context, l net.Listener, id string) error {
 
 			opts := make(map[string][]string)
 			opts[KeySSHID] = []string{id}
-			ctx = metadata.NewOutgoingContext(ctx, opts)
+			ctx := metadata.NewOutgoingContext(ctx, opts)
 
 			stream, err := client.ForwardAgent(ctx)
 			if err != nil {
diff --git a/session/upload/upload.go b/session/upload/upload.go
index e3fce5c1c..30e44eb38 100644
--- a/session/upload/upload.go
+++ b/session/upload/upload.go
@@ -42,7 +42,7 @@ func (u *Upload) WriteTo(w io.Writer) (int64, error) {
 	for {
 		var bm BytesMessage
 		if err := u.cc.RecvMsg(&bm); err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				return n, nil
 			}
 			return n, errors.WithStack(err)
diff --git a/snapshot/localmounter_darwin.go b/snapshot/localmounter_darwin.go
index 8f4646342..9acf3a950 100644
--- a/snapshot/localmounter_darwin.go
+++ b/snapshot/localmounter_darwin.go
@@ -2,11 +2,11 @@ package snapshot
 
 import (
 	"os"
+	"slices"
 
 	"github.com/containerd/containerd/v2/core/mount"
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
-	"slices"
 )
 
 func (lm *localMounter) Mount() (string, error) {
diff --git a/solver/bboltcachestorage/storage.go b/solver/bboltcachestorage/storage.go
index 779e2a15b..bcab0642f 100644
--- a/solver/bboltcachestorage/storage.go
+++ b/solver/bboltcachestorage/storage.go
@@ -307,8 +307,8 @@ func (s *Store) emptyBranchWithParents(tx *bolt.Tx, id []byte) error {
 	}
 
 	// intentionally ignoring errors
-	tx.Bucket([]byte(linksBucket)).DeleteBucket([]byte(id))
-	tx.Bucket([]byte(resultBucket)).DeleteBucket([]byte(id))
+	tx.Bucket([]byte(linksBucket)).DeleteBucket(id)
+	tx.Bucket([]byte(resultBucket)).DeleteBucket(id)
 
 	return nil
 }
@@ -360,7 +360,7 @@ func (s *Store) WalkLinks(id string, link solver.CacheInfoLink, fn func(id strin
 		}
 		index := bytes.Join([][]byte{dt, {}}, []byte("@"))
 		c := b.Cursor()
-		k, _ := c.Seek([]byte(index))
+		k, _ := c.Seek(index)
 		for {
 			if k != nil && bytes.HasPrefix(k, index) {
 				target := bytes.TrimPrefix(k, index)
diff --git a/solver/cachemanager.go b/solver/cachemanager.go
index 2aff1c785..f936eca15 100644
--- a/solver/cachemanager.go
+++ b/solver/cachemanager.go
@@ -388,7 +388,7 @@ func (c *cacheManager) ensurePersistentKey(k *CacheKey) error {
 		for _, ck := range deps {
 			l := CacheInfoLink{
 				Input:    Index(i),
-				Output:   Index(k.Output()),
+				Output:   k.Output(),
 				Digest:   k.Digest(),
 				Selector: ck.Selector,
 			}
@@ -415,7 +415,7 @@ func (c *cacheManager) getIDFromDeps(k *CacheKey) string {
 				m2 := make(map[string]struct{})
 				if err := c.backend.WalkLinks(c.getID(ck.CacheKey.CacheKey), CacheInfoLink{
 					Input:    Index(i),
-					Output:   Index(k.Output()),
+					Output:   k.Output(),
 					Digest:   k.Digest(),
 					Selector: ck.Selector,
 				}, func(id string) error {
diff --git a/solver/debug.go b/solver/debug.go
index aafd81212..29abf173a 100644
--- a/solver/debug.go
+++ b/solver/debug.go
@@ -154,19 +154,20 @@ func debugSchedulerPreUnparkSlow(e *edge, inc []pipeSender, updates, allPipes []
 	}
 
 	for i, up := range updates {
-		if up == e.cacheMapReq {
+		switch up {
+		case e.cacheMapReq:
 			log.
 				WithField("update_index", i).
 				WithField("update_pointer", up).
 				WithField("update_complete", up.Status().Completed).
 				Debug("> update cacheMapReq")
-		} else if up == e.execReq {
+		case e.execReq:
 			log.
 				WithField("update_index", i).
 				WithField("update_pointer", up).
 				WithField("update_complete", up.Status().Completed).
 				Debug("> update execReq")
-		} else {
+		default:
 			st, ok := up.Status().Value.(*edgeState)
 			if ok {
 				index := -1
diff --git a/solver/edge.go b/solver/edge.go
index 109495e2e..389197e00 100644
--- a/solver/edge.go
+++ b/solver/edge.go
@@ -658,7 +658,7 @@ func (e *edge) processDepReq(dep *dep) (depChanged bool) {
 		newKeys := state.keys[len(dep.keys):]
 		if e.cacheMap != nil {
 			e.probeCache(dep, withSelector(newKeys, e.cacheMap.Deps[dep.index].Selector))
-			dep.edgeState.keys = state.keys
+			dep.keys = state.keys
 			if e.allDepsHaveKeys(false) {
 				e.keysDidChange = true
 			}
diff --git a/solver/errdefs/fronetendcap.go b/solver/errdefs/fronetendcap.go
index 72ee63682..d7acf0521 100644
--- a/solver/errdefs/fronetendcap.go
+++ b/solver/errdefs/fronetendcap.go
@@ -17,7 +17,7 @@ type UnsupportedFrontendCapError struct {
 }
 
 func (e *UnsupportedFrontendCapError) Error() string {
-	msg := fmt.Sprintf("unsupported frontend capability %s", e.FrontendCap.Name)
+	msg := fmt.Sprintf("unsupported frontend capability %s", e.Name)
 	if e.error != nil {
 		msg += ": " + e.error.Error()
 	}
diff --git a/solver/errdefs/frontend.go b/solver/errdefs/frontend.go
index ad0e32846..70137878e 100644
--- a/solver/errdefs/frontend.go
+++ b/solver/errdefs/frontend.go
@@ -24,7 +24,7 @@ func (e *FrontendError) Error() string {
 	if e.error != nil {
 		return e.error.Error()
 	}
-	return fmt.Sprintf("frontend %s failed", e.Frontend.Name)
+	return fmt.Sprintf("frontend %s failed", e.Name)
 }
 
 func (e *FrontendError) Unwrap() error {
@@ -44,7 +44,7 @@ func Frontends(err error) []*Frontend {
 	var es *FrontendError
 	if errors.As(err, &es) {
 		out = Frontends(es.Unwrap())
-		out = append(out, es.Frontend.CloneVT())
+		out = append(out, es.CloneVT())
 	}
 	return out
 }
diff --git a/solver/errdefs/solve.go b/solver/errdefs/solve.go
index 3b457550e..691983caf 100644
--- a/solver/errdefs/solve.go
+++ b/solver/errdefs/solve.go
@@ -14,7 +14,7 @@ func init() {
 	typeurl.Register((*Solve)(nil), "github.com/moby/buildkit", "errdefs.Solve+json")
 }
 
-//nolint:revive
+//nolint:revive,staticcheck
 type IsSolve_Subject isSolve_Subject
 
 // SolveError will be returned when an error is encountered during a solve that
diff --git a/solver/errdefs/source.go b/solver/errdefs/source.go
index c599f667f..290ed06db 100644
--- a/solver/errdefs/source.go
+++ b/solver/errdefs/source.go
@@ -14,34 +14,34 @@ func WithSource(err error, src *Source) error {
 	if err == nil {
 		return nil
 	}
-	return &ErrorSource{Source: src, error: err}
+	return &SourceError{Source: src, error: err}
 }
 
-type ErrorSource struct {
+type SourceError struct {
 	*Source
 	error
 }
 
-func (e *ErrorSource) Unwrap() error {
+func (e *SourceError) Unwrap() error {
 	return e.error
 }
 
-func (e *ErrorSource) ToProto() grpcerrors.TypedErrorProto {
+func (e *SourceError) ToProto() grpcerrors.TypedErrorProto {
 	return e.Source
 }
 
 func Sources(err error) []*Source {
 	var out []*Source
-	var es *ErrorSource
+	var es *SourceError
 	if errors.As(err, &es) {
 		out = Sources(es.Unwrap())
-		out = append(out, es.Source.CloneVT())
+		out = append(out, es.CloneVT())
 	}
 	return out
 }
 
 func (s *Source) WrapError(err error) error {
-	return &ErrorSource{error: err, Source: s}
+	return &SourceError{error: err, Source: s}
 }
 
 func (s *Source) Print(w io.Writer) error {
@@ -69,10 +69,7 @@ func (s *Source) Print(w io.Writer) error {
 	var p int
 
 	prepadStart := start
-	for {
-		if p >= pad {
-			break
-		}
+	for p < pad {
 		if start > 1 {
 			start--
 			p++
diff --git a/solver/errdefs/subrequest.go b/solver/errdefs/subrequest.go
index 0fba51d3c..254aebe77 100644
--- a/solver/errdefs/subrequest.go
+++ b/solver/errdefs/subrequest.go
@@ -17,7 +17,7 @@ type UnsupportedSubrequestError struct {
 }
 
 func (e *UnsupportedSubrequestError) Error() string {
-	msg := fmt.Sprintf("unsupported request %s", e.Subrequest.Name)
+	msg := fmt.Sprintf("unsupported request %s", e.Name)
 	if e.error != nil {
 		msg += ": " + e.error.Error()
 	}
diff --git a/solver/index.go b/solver/index.go
index de6a8fbe5..c640e3b10 100644
--- a/solver/index.go
+++ b/solver/index.go
@@ -97,7 +97,7 @@ func (ei *edgeIndex) LoadOrStore(k *CacheKey, e *edge) *edge {
 		}
 	}
 
-	if old != nil && !(!isIgnoreCache(old) && isIgnoreCache(e)) {
+	if old != nil && (isIgnoreCache(old) || !isIgnoreCache(e)) {
 		ei.enforceLinked(oldID, k)
 		return old
 	}
@@ -190,7 +190,7 @@ func (ei *edgeIndex) getAllMatches(k *CacheKey) []string {
 		if i == 0 {
 			for _, d := range dd {
 				ll := CacheInfoLink{Input: Index(i), Digest: k.Digest(), Output: k.Output(), Selector: d.Selector}
-				for _, ckID := range d.CacheKey.CacheKey.indexIDs {
+				for _, ckID := range d.CacheKey.indexIDs {
 					item, ok := ei.items[ckID]
 					if ok {
 						for l := range item.links[ll] {
@@ -210,7 +210,7 @@ func (ei *edgeIndex) getAllMatches(k *CacheKey) []string {
 			found := false
 			for _, d := range dd {
 				ll := CacheInfoLink{Input: Index(i), Digest: k.Digest(), Output: k.Output(), Selector: d.Selector}
-				for _, ckID := range d.CacheKey.CacheKey.indexIDs {
+				for _, ckID := range d.CacheKey.indexIDs {
 					if item, ok := ei.items[ckID]; ok {
 						if l, ok := item.links[ll]; ok {
 							if _, ok := l[m]; ok {
diff --git a/solver/jobs.go b/solver/jobs.go
index 030eef03c..2e4a95475 100644
--- a/solver/jobs.go
+++ b/solver/jobs.go
@@ -625,7 +625,7 @@ func (jl *Solver) NewJob(id string) (*Job, error) {
 
 func (jl *Solver) Get(id string) (*Job, error) {
 	ctx, cancel := context.WithCancelCause(context.Background())
-	ctx, _ = context.WithTimeoutCause(ctx, 6*time.Second, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, 6*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	go func() {
diff --git a/solver/llbsolver/bridge.go b/solver/llbsolver/bridge.go
index 1320be8fa..15d962472 100644
--- a/solver/llbsolver/bridge.go
+++ b/solver/llbsolver/bridge.go
@@ -265,7 +265,7 @@ func (rp *resultProxy) wrapError(err error) error {
 	var ve *errdefs.VertexError
 	if errors.As(err, &ve) {
 		if rp.req.Definition.Source != nil {
-			locs, ok := rp.req.Definition.Source.Locations[string(ve.Digest)]
+			locs, ok := rp.req.Definition.Source.Locations[ve.Digest]
 			if ok {
 				for _, loc := range locs.Locations {
 					err = errdefs.WithSource(err, &errdefs.Source{
diff --git a/solver/llbsolver/cdidevices/manager.go b/solver/llbsolver/cdidevices/manager.go
index 274c6a40d..94527e7d7 100644
--- a/solver/llbsolver/cdidevices/manager.go
+++ b/solver/llbsolver/cdidevices/manager.go
@@ -271,7 +271,7 @@ func deviceAnnotations(dev *cdi.Device) map[string]string {
 	// spec annotations
 	maps.Copy(out, dev.GetSpec().Annotations)
 	// device annotations
-	maps.Copy(out, dev.Device.Annotations)
+	maps.Copy(out, dev.Annotations)
 	return out
 }
 
diff --git a/solver/llbsolver/history.go b/solver/llbsolver/history.go
index 07f63670d..27e4d2e38 100644
--- a/solver/llbsolver/history.go
+++ b/solver/llbsolver/history.go
@@ -448,7 +448,7 @@ func (h *HistoryQueue) addResource(ctx context.Context, l leases.Lease, desc *co
 				return err
 			}
 			defer lr.Discard()
-			ok, err := h.migrateBlobV2(ctx, string(desc.Digest), detectSkipLayers)
+			ok, err := h.migrateBlobV2(ctx, desc.Digest, detectSkipLayers)
 			if err != nil {
 				return err
 			}
@@ -458,7 +458,7 @@ func (h *HistoryQueue) addResource(ctx context.Context, l leases.Lease, desc *co
 		}
 	}
 	return h.hLeaseManager.AddResource(ctx, l, leases.Resource{
-		ID:   string(desc.Digest),
+		ID:   desc.Digest,
 		Type: "content",
 	})
 }
diff --git a/solver/llbsolver/mounts/mount.go b/solver/llbsolver/mounts/mount.go
index 93d97a907..58a962a80 100644
--- a/solver/llbsolver/mounts/mount.go
+++ b/solver/llbsolver/mounts/mount.go
@@ -500,7 +500,7 @@ func (r *cacheRefShare) release(ctx context.Context) error {
 	if r.main != nil {
 		delete(r.main.shares, r.key)
 	}
-	return r.MutableRef.Release(ctx)
+	return r.Release(ctx)
 }
 
 var (
diff --git a/solver/llbsolver/ops/exec.go b/solver/llbsolver/ops/exec.go
index 894a90cc5..9bf9a3551 100644
--- a/solver/llbsolver/ops/exec.go
+++ b/solver/llbsolver/ops/exec.go
@@ -563,7 +563,7 @@ func (e *ExecOp) loadSecretEnv(ctx context.Context, g session.Group) ([]string,
 			}
 			return nil
 		})
-		if err != nil && !(errors.Is(err, secrets.ErrNotFound) && sopt.Optional) {
+		if err != nil && (!errors.Is(err, secrets.ErrNotFound) || !sopt.Optional) {
 			return nil, err
 		}
 		out = append(out, fmt.Sprintf("%s=%s", sopt.Name, string(dt)))
diff --git a/solver/llbsolver/proc/provenance.go b/solver/llbsolver/proc/provenance.go
index 0bd4f4255..618906866 100644
--- a/solver/llbsolver/proc/provenance.go
+++ b/solver/llbsolver/proc/provenance.go
@@ -66,8 +66,8 @@ func ProvenanceProcessor(attrs map[string]string) llbsolver.Processor {
 					PredicateType: slsa02.PredicateSLSAProvenance,
 				},
 				Path: filename,
-				ContentFunc: func() ([]byte, error) {
-					pr, err := pc.Predicate()
+				ContentFunc: func(ctx context.Context) ([]byte, error) {
+					pr, err := pc.Predicate(ctx)
 					if err != nil {
 						return nil, err
 					}
diff --git a/solver/llbsolver/provenance.go b/solver/llbsolver/provenance.go
index f61640af5..e3423a764 100644
--- a/solver/llbsolver/provenance.go
+++ b/solver/llbsolver/provenance.go
@@ -168,12 +168,12 @@ func (b *provenanceBridge) Solve(ctx context.Context, req frontend.SolveRequest,
 		b.builds = append(b.builds, resultWithBridge{res: res, bridge: b})
 		b.mu.Unlock()
 	} else if req.Frontend != "" {
-		f, ok := b.llbBridge.frontends[req.Frontend]
+		f, ok := b.frontends[req.Frontend]
 		if !ok {
 			return nil, errors.Errorf("invalid frontend: %s", req.Frontend)
 		}
 		wb := &provenanceBridge{llbBridge: b.llbBridge, req: &req}
-		res, err = f.Solve(ctx, wb, b.llbBridge, req.FrontendOpt, req.FrontendInputs, sid, b.llbBridge.sm)
+		res, err = f.Solve(ctx, wb, b.llbBridge, req.FrontendOpt, req.FrontendInputs, sid, b.sm)
 		if err != nil {
 			fe := errdefs.Frontend{
 				Name:   req.Frontend,
@@ -333,7 +333,7 @@ type ProvenanceCreator struct {
 	pr        *provenancetypes.ProvenancePredicate
 	j         *solver.Job
 	sampler   *resources.SysSampler
-	addLayers func() error
+	addLayers func(context.Context) error
 }
 
 func NewProvenanceCreator(ctx context.Context, cp *provenance.Capture, res solver.ResultProxy, attrs map[string]string, j *solver.Job, usage *resources.SysSampler) (*ProvenanceCreator, error) {
@@ -377,7 +377,7 @@ func NewProvenanceCreator(ctx context.Context, cp *provenance.Capture, res solve
 
 	pr.Builder.ID = attrs["builder-id"]
 
-	var addLayers func() error
+	var addLayers func(context.Context) error
 
 	switch mode {
 	case "min":
@@ -408,7 +408,7 @@ func NewProvenanceCreator(ctx context.Context, cp *provenance.Capture, res solve
 			return nil, errors.Errorf("invalid worker ref %T", r.Sys())
 		}
 
-		addLayers = func() error {
+		addLayers = func(ctx context.Context) error {
 			e := newCacheExporter()
 
 			if wref.ImmutableRef != nil {
@@ -460,12 +460,12 @@ func NewProvenanceCreator(ctx context.Context, cp *provenance.Capture, res solve
 	return pc, nil
 }
 
-func (p *ProvenanceCreator) Predicate() (*provenancetypes.ProvenancePredicate, error) {
+func (p *ProvenanceCreator) Predicate(ctx context.Context) (*provenancetypes.ProvenancePredicate, error) {
 	end := p.j.RegisterCompleteTime()
 	p.pr.Metadata.BuildFinishedOn = &end
 
 	if p.addLayers != nil {
-		if err := p.addLayers(); err != nil {
+		if err := p.addLayers(ctx); err != nil {
 			return nil, err
 		}
 	}
diff --git a/solver/llbsolver/solver.go b/solver/llbsolver/solver.go
index 32ca3da84..36fc7fd08 100644
--- a/solver/llbsolver/solver.go
+++ b/solver/llbsolver/solver.go
@@ -207,7 +207,7 @@ func (s *Solver) recordBuildHistory(ctx context.Context, id string, req frontend
 		}
 
 		ctx, cancel := context.WithCancelCause(ctx)
-		ctx, _ = context.WithTimeoutCause(ctx, 300*time.Second, errors.WithStack(context.DeadlineExceeded))
+		ctx, _ = context.WithTimeoutCause(ctx, 300*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 		defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 		var mu sync.Mutex
@@ -237,7 +237,7 @@ func (s *Solver) recordBuildHistory(ctx context.Context, id string, req frontend
 			if err != nil {
 				return nil, nil, err
 			}
-			pr, err := prc.Predicate()
+			pr, err := prc.Predicate(ctx)
 			if err != nil {
 				return nil, nil, err
 			}
@@ -676,7 +676,7 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro
 
 func (s *Solver) getSessionExporters(ctx context.Context, sessionID string, id int, inp *exporter.Source) ([]exporter.ExporterInstance, error) {
 	timeoutCtx, cancel := context.WithCancelCause(ctx)
-	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	caller, err := s.sm.Get(timeoutCtx, sessionID, false)
@@ -753,10 +753,10 @@ func runCacheExporters(ctx context.Context, exporters []RemoteCacheExporter, j *
 		i, exp := i, exp
 		eg.Go(func() (err error) {
 			id := fmt.Sprint(j.SessionID, "-cache-", i)
-			err = inBuilderContext(ctx, j, exp.Exporter.Name(), id, func(ctx context.Context, _ session.Group) error {
+			err = inBuilderContext(ctx, j, exp.Name(), id, func(ctx context.Context, _ session.Group) error {
 				prepareDone := progress.OneOff(ctx, "preparing build cache for export")
 				if err := result.EachRef(cached, inp, func(res solver.CachedResult, ref cache.ImmutableRef) error {
-					ctx = withDescHandlerCacheOpts(ctx, ref)
+					ctx := withDescHandlerCacheOpts(ctx, ref)
 
 					// Configure compression
 					compressionConfig := exp.Config().Compression
diff --git a/solver/progress.go b/solver/progress.go
index 90afca1f5..65d180234 100644
--- a/solver/progress.go
+++ b/solver/progress.go
@@ -2,6 +2,7 @@ package solver
 
 import (
 	"context"
+	"errors"
 	"io"
 	"slices"
 	"time"
@@ -26,7 +27,7 @@ func (j *Job) Status(ctx context.Context, ch chan *client.SolveStatus) error {
 	for {
 		p, err := pr.Read(ctx)
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				return nil
 			}
 			return err
diff --git a/solver/result.go b/solver/result.go
index 2ba1ef9bc..e5f4b57e1 100644
--- a/solver/result.go
+++ b/solver/result.go
@@ -48,7 +48,7 @@ type splitResult struct {
 
 func (r *splitResult) Release(ctx context.Context) error {
 	if atomic.AddInt64(&r.released, 1) > 1 {
-		err := errors.Errorf("releasing already released reference %+v", r.Result.ID())
+		err := errors.Errorf("releasing already released reference %+v", r.ID())
 		bklog.G(ctx).Error(err)
 		return err
 	}
diff --git a/source/containerimage/ocilayout.go b/source/containerimage/ocilayout.go
index 0fe0b3469..c5e9ef0ab 100644
--- a/source/containerimage/ocilayout.go
+++ b/source/containerimage/ocilayout.go
@@ -125,7 +125,7 @@ func (r *ociLayoutResolver) info(ctx context.Context, ref reference.Spec) (conte
 func (r *ociLayoutResolver) withCaller(ctx context.Context, f func(context.Context, session.Caller) error) error {
 	if r.store.SessionID != "" {
 		timeoutCtx, cancel := context.WithCancelCause(ctx)
-		timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+		timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 		defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 		caller, err := r.sm.Get(timeoutCtx, r.store.SessionID, false)
diff --git a/source/containerimage/pull.go b/source/containerimage/pull.go
index 023848395..41f06aded 100644
--- a/source/containerimage/pull.go
+++ b/source/containerimage/pull.go
@@ -88,11 +88,11 @@ func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (cach
 	switch p.ResolverType {
 	case ResolverTypeRegistry:
 		resolver := resolver.DefaultPool.GetResolver(p.RegistryHosts, p.Ref, "pull", p.SessionManager, g).WithImageStore(p.ImageStore, p.Mode)
-		p.Puller.Resolver = resolver
+		p.Resolver = resolver
 		getResolver = func(g session.Group) remotes.Resolver { return resolver.WithSession(g) }
 	case ResolverTypeOCILayout:
 		resolver := getOCILayoutResolver(p.store, p.SessionManager, g)
-		p.Puller.Resolver = resolver
+		p.Resolver = resolver
 		// OCILayout has no need for session
 		getResolver = func(g session.Group) remotes.Resolver { return resolver }
 	default:
@@ -203,11 +203,11 @@ func (p *puller) Snapshot(ctx context.Context, g session.Group) (ir cache.Immuta
 	switch p.ResolverType {
 	case ResolverTypeRegistry:
 		resolver := resolver.DefaultPool.GetResolver(p.RegistryHosts, p.Ref, "pull", p.SessionManager, g).WithImageStore(p.ImageStore, p.Mode)
-		p.Puller.Resolver = resolver
+		p.Resolver = resolver
 		getResolver = func(g session.Group) remotes.Resolver { return resolver.WithSession(g) }
 	case ResolverTypeOCILayout:
 		resolver := getOCILayoutResolver(p.store, p.SessionManager, g)
-		p.Puller.Resolver = resolver
+		p.Resolver = resolver
 		// OCILayout has no need for session
 		getResolver = func(g session.Group) remotes.Resolver { return resolver }
 	default:
diff --git a/source/git/source_unix_nolinux.go b/source/git/source_unix_nolinux.go
index 5c58aa9f6..f59249fca 100644
--- a/source/git/source_unix_nolinux.go
+++ b/source/git/source_unix_nolinux.go
@@ -4,6 +4,7 @@ package git
 
 import (
 	"context"
+	"errors"
 	"os"
 	"os/exec"
 	"os/signal"
@@ -59,7 +60,8 @@ func gitMain() {
 	err := cmd.Run()
 	close(done)
 	if err != nil {
-		if exiterr, ok := err.(*exec.ExitError); ok {
+		exiterr := &exec.ExitError{}
+		if errors.As(err, &exiterr) {
 			switch status := exiterr.Sys().(type) {
 			case unix.WaitStatus:
 				os.Exit(status.ExitStatus())
diff --git a/source/http/source.go b/source/http/source.go
index 819a71812..574ef95f3 100644
--- a/source/http/source.go
+++ b/source/http/source.go
@@ -398,7 +398,7 @@ func (hs *httpSourceHandler) save(ctx context.Context, resp *http.Response, s se
 	uid := hs.src.UID
 	gid := hs.src.GID
 	if idmap := mount.IdentityMapping(); idmap != nil {
-		uid, gid, err = idmap.ToHost(int(uid), int(gid))
+		uid, gid, err = idmap.ToHost(uid, gid)
 		if err != nil {
 			return nil, "", err
 		}
@@ -496,7 +496,7 @@ func (hs *httpSourceHandler) Snapshot(ctx context.Context, g session.Group) (cac
 }
 
 func (hs *httpSourceHandler) newHTTPRequest(ctx context.Context, g session.Group) (*http.Request, error) {
-	req, err := http.NewRequest("GET", hs.src.URL, nil)
+	req, err := http.NewRequest(http.MethodGet, hs.src.URL, nil)
 	if err != nil {
 		return nil, err
 	}
diff --git a/source/http/transport.go b/source/http/transport.go
index e511e8634..a42f53944 100644
--- a/source/http/transport.go
+++ b/source/http/transport.go
@@ -25,7 +25,7 @@ func (h *sessionHandler) RoundTrip(req *http.Request) (*http.Response, error) {
 		return h.rt.RoundTrip(req)
 	}
 
-	if req.Method != "GET" {
+	if req.Method != http.MethodGet {
 		return nil, errors.Errorf("invalid request")
 	}
 
@@ -44,7 +44,7 @@ func (h *sessionHandler) RoundTrip(req *http.Request) (*http.Response, error) {
 
 		resp = &http.Response{
 			Status:        "200 OK",
-			StatusCode:    200,
+			StatusCode:    http.StatusOK,
 			Body:          pr,
 			ContentLength: -1,
 		}
diff --git a/source/local/source.go b/source/local/source.go
index db4f9fe67..f65fd5637 100644
--- a/source/local/source.go
+++ b/source/local/source.go
@@ -164,7 +164,7 @@ func (ls *localSourceHandler) Snapshot(ctx context.Context, g session.Group) (ca
 	}
 
 	timeoutCtx, cancel := context.WithCancelCause(ctx)
-	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+	timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	caller, err := ls.sm.Get(timeoutCtx, sessionID, false)
diff --git a/sourcepolicy/engine.go b/sourcepolicy/engine.go
index 624c8fd1d..4a6100b83 100644
--- a/sourcepolicy/engine.go
+++ b/sourcepolicy/engine.go
@@ -74,6 +74,7 @@ func (e *Engine) Evaluate(ctx context.Context, op *pb.SourceOp) (bool, error) {
 			return mutated, errors.Wrapf(ErrTooManyOps, "too many mutations on a single source")
 		}
 
+		ctx := ctx
 		if i == 0 {
 			ctx = bklog.WithLogger(ctx, bklog.G(ctx).WithField("orig", op))
 		} else {
diff --git a/sourcepolicy/pb/json.go b/sourcepolicy/pb/json.go
index 9ca101eb7..4b61d0a6d 100644
--- a/sourcepolicy/pb/json.go
+++ b/sourcepolicy/pb/json.go
@@ -1,4 +1,4 @@
-package moby_buildkit_v1_sourcepolicy //nolint:revive
+package moby_buildkit_v1_sourcepolicy //nolint:revive,staticcheck
 
 import (
 	"github.com/moby/buildkit/util/gogo/proto"
diff --git a/util/appcontext/appcontext.go b/util/appcontext/appcontext.go
index d5a785ef6..28626fd7a 100644
--- a/util/appcontext/appcontext.go
+++ b/util/appcontext/appcontext.go
@@ -25,11 +25,11 @@ func Context() context.Context {
 
 		ctx := context.Background()
 		for _, f := range inits {
-			ctx = f(ctx)
+			ctx = f(ctx) //nolint:fatcontext
 		}
 
 		ctx, cancel := context.WithCancelCause(ctx)
-		appContextCache = ctx
+		appContextCache = ctx //nolint:fatcontext
 
 		go func() {
 			for {
diff --git a/util/archutil/check_unix.go b/util/archutil/check_unix.go
index f99decd64..87f54b54b 100644
--- a/util/archutil/check_unix.go
+++ b/util/archutil/check_unix.go
@@ -57,7 +57,8 @@ func check(arch, bin string) (string, error) {
 	if err == nil {
 		return "", errors.Errorf("invalid zero exit code")
 	}
-	if exitError, ok := err.(*exec.ExitError); ok {
+	exitError := &exec.ExitError{}
+	if errors.As(err, &exitError) {
 		switch exitError.ExitCode() {
 		case 65:
 			return "v1", nil
diff --git a/util/compression/estargz.go b/util/compression/estargz.go
index ba68896aa..de4bbec3f 100644
--- a/util/compression/estargz.go
+++ b/util/compression/estargz.go
@@ -191,7 +191,7 @@ func (c estargzType) Is(ctx context.Context, cs content.Store, dgst digest.Diges
 		if h.Name != estargz.TOCTarName {
 			return false
 		}
-		if _, err = tr.Next(); err != io.EOF { // must be EOF
+		if _, err = tr.Next(); !errors.Is(err, io.EOF) { // must be EOF
 			return false
 		}
 
diff --git a/util/contentutil/copy.go b/util/contentutil/copy.go
index 505a08187..c1c10b5af 100644
--- a/util/contentutil/copy.go
+++ b/util/contentutil/copy.go
@@ -27,7 +27,7 @@ type localFetcher struct {
 }
 
 func (f *localFetcher) Fetch(ctx context.Context, desc ocispecs.Descriptor) (io.ReadCloser, error) {
-	r, err := f.Provider.ReaderAt(ctx, desc)
+	r, err := f.ReaderAt(ctx, desc)
 	if err != nil {
 		return nil, err
 	}
@@ -42,7 +42,7 @@ type rc struct {
 func (r *rc) Read(b []byte) (int, error) {
 	n, err := r.ReadAt(b, r.offset)
 	r.offset += int64(n)
-	if n > 0 && err == io.EOF {
+	if n > 0 && errors.Is(err, io.EOF) {
 		err = nil
 	}
 	return n, err
diff --git a/util/contentutil/fetcher.go b/util/contentutil/fetcher.go
index f7105fd9e..560b9fcfc 100644
--- a/util/contentutil/fetcher.go
+++ b/util/contentutil/fetcher.go
@@ -54,8 +54,8 @@ func (r *readerAt) ReadAt(b []byte, off int64) (int, error) {
 
 	var totalN int
 	for len(b) > 0 {
-		n, err := r.Reader.Read(b)
-		if err == io.EOF && n == len(b) {
+		n, err := r.Read(b)
+		if errors.Is(err, io.EOF) && n == len(b) {
 			err = nil
 		}
 		r.offset += int64(n)
diff --git a/util/converter/tarconverter/tarconverter.go b/util/converter/tarconverter/tarconverter.go
index 8574877d5..4d7edd08d 100644
--- a/util/converter/tarconverter/tarconverter.go
+++ b/util/converter/tarconverter/tarconverter.go
@@ -2,6 +2,7 @@ package tarconverter
 
 import (
 	"archive/tar"
+	"errors"
 	"io"
 )
 
@@ -19,7 +20,7 @@ func NewReader(srcContent io.Reader, headerConverter HeaderConverter) io.ReadClo
 
 		for {
 			hdr, err := srcTar.Next()
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				// Signals end of archive.
 				rebasedTar.Close()
 				// drain the reader into io.Discard, until hitting EOF
diff --git a/util/disk/disk_freebsd.go b/util/disk/disk_freebsd.go
index 755a834c3..7d422240c 100644
--- a/util/disk/disk_freebsd.go
+++ b/util/disk/disk_freebsd.go
@@ -17,6 +17,6 @@ func GetDiskStat(root string) (DiskStat, error) {
 	return DiskStat{
 		Total:     int64(st.Bsize) * int64(st.Blocks),
 		Free:      int64(st.Bsize) * int64(st.Bfree),
-		Available: int64(st.Bsize) * int64(st.Bavail),
+		Available: int64(st.Bsize) * st.Bavail,
 	}, nil
 }
diff --git a/util/entitlements/security/security_linux.go b/util/entitlements/security/security_linux.go
index 59f574a7d..cc5cd76d4 100644
--- a/util/entitlements/security/security_linux.go
+++ b/util/entitlements/security/security_linux.go
@@ -120,7 +120,7 @@ func getFreeLoopID() (int, error) {
 	}
 	defer fd.Close()
 
-	const _LOOP_CTL_GET_FREE = 0x4C82 //nolint:revive
+	const _LOOP_CTL_GET_FREE = 0x4C82 //nolint:revive,staticcheck
 	r1, _, uerr := unix.Syscall(unix.SYS_IOCTL, fd.Fd(), _LOOP_CTL_GET_FREE, 0)
 	if uerr == 0 {
 		return int(r1), nil
diff --git a/util/flightcontrol/flightcontrol.go b/util/flightcontrol/flightcontrol.go
index 92237516a..e986d6764 100644
--- a/util/flightcontrol/flightcontrol.go
+++ b/util/flightcontrol/flightcontrol.go
@@ -299,7 +299,7 @@ func (ps *progressState) run(pr progress.Reader) {
 	for {
 		p, err := pr.Read(context.TODO())
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				ps.mu.Lock()
 				ps.done = true
 				ps.mu.Unlock()
diff --git a/util/grpcerrors/grpcerrors.go b/util/grpcerrors/grpcerrors.go
index adcce39a2..8689dfff0 100644
--- a/util/grpcerrors/grpcerrors.go
+++ b/util/grpcerrors/grpcerrors.go
@@ -139,7 +139,7 @@ func Code(err error) codes.Code {
 }
 
 func WrapCode(err error, code codes.Code) error {
-	return &withCode{error: err, code: code}
+	return &withCodeError{error: err, code: code}
 }
 
 func AsGRPCStatus(err error) (*status.Status, bool) {
@@ -237,16 +237,16 @@ func (e *grpcStatusError) GRPCStatus() *status.Status {
 	return e.st
 }
 
-type withCode struct {
+type withCodeError struct {
 	code codes.Code
 	error
 }
 
-func (e *withCode) Code() codes.Code {
+func (e *withCodeError) Code() codes.Code {
 	return e.code
 }
 
-func (e *withCode) Unwrap() error {
+func (e *withCodeError) Unwrap() error {
 	return e.error
 }
 
diff --git a/util/network/cniprovider/cni.go b/util/network/cniprovider/cni.go
index bf464ee12..24a8c2b4a 100644
--- a/util/network/cniprovider/cni.go
+++ b/util/network/cniprovider/cni.go
@@ -282,10 +282,10 @@ func (c *cniProvider) newNS(ctx context.Context, hostname string) (*cniNS, error
 
 	var cniRes *cni.Result
 	if ctx.Value(contextKeyDetachedNetNS) == nil {
-		cniRes, err = c.CNI.Setup(context.TODO(), id, nativeID, nsOpts...)
+		cniRes, err = c.Setup(context.TODO(), id, nativeID, nsOpts...)
 	} else {
 		// Parallel Setup cannot be used, apparently due to the goroutine issue with setns
-		cniRes, err = c.CNI.SetupSerially(context.TODO(), id, nativeID, nsOpts...)
+		cniRes, err = c.SetupSerially(context.TODO(), id, nativeID, nsOpts...)
 	}
 	if err != nil {
 		deleteNetNS(nativeID)
diff --git a/util/network/cniprovider/cni_linux.go b/util/network/cniprovider/cni_linux.go
index 4b393eab6..526fc71bc 100644
--- a/util/network/cniprovider/cni_linux.go
+++ b/util/network/cniprovider/cni_linux.go
@@ -86,7 +86,7 @@ func withDetachedNetNSIfAny(ctx context.Context, fn func(context.Context) error)
 		detachedNetNS := filepath.Join(stateDir, "netns")
 		if _, err := os.Lstat(detachedNetNS); !errors.Is(err, os.ErrNotExist) {
 			return ns.WithNetNSPath(detachedNetNS, func(_ ns.NetNS) error {
-				ctx = context.WithValue(ctx, contextKeyDetachedNetNS, detachedNetNS)
+				ctx := context.WithValue(ctx, contextKeyDetachedNetNS, detachedNetNS)
 				bklog.G(ctx).Debugf("Entering RootlessKit's detached netns %q", detachedNetNS)
 				err2 := fn(ctx)
 				bklog.G(ctx).WithError(err2).Debugf("Leaving RootlessKit's detached netns %q", detachedNetNS)
diff --git a/util/network/cniprovider/createns_linux.go b/util/network/cniprovider/createns_linux.go
index 078ce821f..95e086992 100644
--- a/util/network/cniprovider/createns_linux.go
+++ b/util/network/cniprovider/createns_linux.go
@@ -94,7 +94,7 @@ func setNetNS(s *specs.Spec, nsPath string) error {
 
 func unmountNetNS(nsPath string) error {
 	if err := unix.Unmount(nsPath, unix.MNT_DETACH); err != nil {
-		if err != syscall.EINVAL && err != syscall.ENOENT {
+		if !errors.Is(err, syscall.EINVAL) && !errors.Is(err, syscall.ENOENT) {
 			return errors.Wrap(err, "error unmounting network namespace")
 		}
 	}
diff --git a/util/overlay/overlay_linux.go b/util/overlay/overlay_linux.go
index 39b240515..223c6655d 100644
--- a/util/overlay/overlay_linux.go
+++ b/util/overlay/overlay_linux.go
@@ -273,7 +273,7 @@ func checkOpaque(upperdir string, path string, base string, f os.FileInfo) (isOp
 	if f.IsDir() {
 		for _, oKey := range []string{"trusted.overlay.opaque", "user.overlay.opaque"} {
 			opaque, err := sysx.LGetxattr(filepath.Join(upperdir, path), oKey)
-			if err != nil && err != unix.ENODATA {
+			if err != nil && !errors.Is(err, unix.ENODATA) {
 				return false, errors.Wrapf(err, "failed to retrieve %s attr", oKey)
 			} else if len(opaque) == 1 && opaque[0] == 'y' {
 				// This is an opaque whiteout directory.
@@ -296,7 +296,7 @@ func checkRedirect(upperdir string, path string, f os.FileInfo) (bool, error) {
 	if f.IsDir() {
 		rKey := "trusted.overlay.redirect"
 		redirect, err := sysx.LGetxattr(filepath.Join(upperdir, path), rKey)
-		if err != nil && err != unix.ENODATA {
+		if err != nil && !errors.Is(err, unix.ENODATA) {
 			return false, errors.Wrapf(err, "failed to retrieve %s attr", rKey)
 		}
 		return len(redirect) > 0, nil
@@ -379,11 +379,11 @@ func compareSysStat(s1, s2 any) (bool, error) {
 // Copyright The containerd Authors.
 func compareCapabilities(p1, p2 string) (bool, error) {
 	c1, err := sysx.LGetxattr(p1, "security.capability")
-	if err != nil && err != sysx.ENODATA {
+	if err != nil && !errors.Is(err, sysx.ENODATA) {
 		return false, errors.Wrapf(err, "failed to get xattr for %s", p1)
 	}
 	c2, err := sysx.LGetxattr(p2, "security.capability")
-	if err != nil && err != sysx.ENODATA {
+	if err != nil && !errors.Is(err, sysx.ENODATA) {
 		return false, errors.Wrapf(err, "failed to get xattr for %s", p2)
 	}
 	return bytes.Equal(c1, c2), nil
@@ -443,7 +443,7 @@ func compareFileContent(p1, p2 string) (bool, error) {
 	defer bufPool.Put(b2)
 	for {
 		n1, err1 := io.ReadFull(f1, *b1)
-		if err1 == io.ErrUnexpectedEOF {
+		if errors.Is(err1, io.ErrUnexpectedEOF) {
 			// it's expected to get EOF when file size isn't a multiple of chunk size, consolidate these error types
 			err1 = io.EOF
 		}
@@ -451,7 +451,7 @@ func compareFileContent(p1, p2 string) (bool, error) {
 			return false, err1
 		}
 		n2, err2 := io.ReadFull(f2, *b2)
-		if err2 == io.ErrUnexpectedEOF {
+		if errors.Is(err2, io.ErrUnexpectedEOF) {
 			err2 = io.EOF
 		}
 		if err2 != nil && err2 != io.EOF {
diff --git a/util/progress/logs/logs.go b/util/progress/logs/logs.go
index 2ed1c2610..36bf32bf9 100644
--- a/util/progress/logs/logs.go
+++ b/util/progress/logs/logs.go
@@ -173,7 +173,7 @@ func LoggerFromContext(ctx context.Context) func([]byte) {
 		defer pw.Close()
 		pw.Write(identity.NewID(), client.VertexLog{
 			Stream: stderr,
-			Data:   []byte(dt),
+			Data:   dt,
 		})
 	}
 }
diff --git a/util/progress/multireader.go b/util/progress/multireader.go
index 6afcca9fe..bcc9eb897 100644
--- a/util/progress/multireader.go
+++ b/util/progress/multireader.go
@@ -2,6 +2,7 @@ package progress
 
 import (
 	"context"
+	"errors"
 	"io"
 	"sync"
 )
@@ -110,7 +111,7 @@ func (mr *MultiReader) handle() error {
 	for {
 		p, err := mr.main.Read(context.TODO())
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				mr.mu.Lock()
 				cancelErr := context.Canceled
 				for w, c := range mr.writers {
diff --git a/util/progress/progressui/colors.go b/util/progress/progressui/colors.go
index e48535960..9dd7b3247 100644
--- a/util/progress/progressui/colors.go
+++ b/util/progress/progressui/colors.go
@@ -40,7 +40,7 @@ func setUserDefinedTermColors(colorsEnv string) {
 	for _, field := range fields {
 		k, v, ok := strings.Cut(field, "=")
 		if !ok || strings.Contains(v, "=") {
-			err := errors.New("A valid entry must have exactly two fields")
+			err := errors.New("valid entry must have exactly two fields")
 			bklog.L.WithError(err).Warnf("Could not parse BUILDKIT_COLORS component: %s", field)
 			continue
 		}
@@ -52,7 +52,7 @@ func setUserDefinedTermColors(colorsEnv string) {
 				parseKeys(k, c)
 			}
 		} else {
-			err := errors.New("Colors must be a name from the pre-defined list or a valid 3-part RGB value")
+			err := errors.New("colors must be a name from the pre-defined list or a valid 3-part RGB value")
 			bklog.L.WithError(err).Warnf("Unknown color value found in BUILDKIT_COLORS: %s=%s", k, v)
 		}
 	}
@@ -63,7 +63,7 @@ func readBuildkitColorsEnv(colorsEnv string) []string {
 	csvReader.Comma = ':'
 	fields, err := csvReader.Fields(colorsEnv, nil)
 	if err != nil {
-		bklog.L.WithError(err).Warnf("Could not parse BUILDKIT_COLORS. Falling back to defaults.")
+		bklog.L.WithError(err).Warnf("could not parse BUILDKIT_COLORS. Falling back to defaults.")
 		return nil
 	}
 	return fields
@@ -76,7 +76,7 @@ func readRGB(v string) aec.ANSI {
 		return nil
 	}
 	if len(fields) != 3 {
-		err = errors.New("A valid RGB color must have three fields")
+		err = errors.New("valid RGB color must have three fields")
 		bklog.L.WithError(err).Warnf("Could not parse value %s as valid RGB color. Ignoring.", v)
 		return nil
 	}
diff --git a/util/progress/progressui/display.go b/util/progress/progressui/display.go
index 04b38baaf..16a2ece63 100644
--- a/util/progress/progressui/display.go
+++ b/util/progress/progressui/display.go
@@ -588,10 +588,8 @@ func (t *trace) triggerVertexEvent(v *client.Vertex) {
 		old = *v
 	}
 
-	changed := false
-	if v.Digest != old.Digest {
-		changed = true
-	}
+	changed := v.Digest != old.Digest
+
 	if v.Name != old.Name {
 		changed = true
 	}
@@ -674,7 +672,7 @@ func (t *trace) update(s *client.SolveStatus, termWidth int) {
 			t.vertexes = append(t.vertexes, t.byDigest[v.Digest])
 		}
 		// allow a duplicate initial vertex that shouldn't reset state
-		if !(prev != nil && prev.isStarted() && v.Started == nil) {
+		if prev == nil || !prev.isStarted() || v.Started != nil {
 			t.byDigest[v.Digest].Vertex = v
 		}
 		if v.Started != nil {
diff --git a/util/progress/progressui/printer.go b/util/progress/progressui/printer.go
index 338079d47..61443ca33 100644
--- a/util/progress/progressui/printer.go
+++ b/util/progress/progressui/printer.go
@@ -147,7 +147,7 @@ func (p *textMux) printVtx(t *trace, dgst digest.Digest) {
 			l = l[v.logsOffset:]
 			fmt.Fprintf(p.w, "%s", l)
 		} else {
-			fmt.Fprintf(p.w, "#%d %s", v.index, []byte(l))
+			fmt.Fprintf(p.w, "#%d %s", v.index, l)
 		}
 
 		if i != len(v.logs)-1 || !v.logsPartial {
diff --git a/util/resolver/authorizer.go b/util/resolver/authorizer.go
index 386377221..89fe6785d 100644
--- a/util/resolver/authorizer.go
+++ b/util/resolver/authorizer.go
@@ -153,7 +153,8 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
 	handler := a.handlers.get(ctx, host, a.sm, a.session)
 
 	for _, c := range auth.ParseAuthHeader(last.Header) {
-		if c.Scheme == auth.BearerAuth {
+		switch c.Scheme {
+		case auth.BearerAuth:
 			var oldScopes []string
 			if err := invalidAuthorization(c, responses); err != nil {
 				a.handlers.delete(handler)
@@ -200,7 +201,7 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
 			a.handlers.set(host, sessionID, newAuthHandler(host, a.client, c.Scheme, pubKey, common))
 
 			return nil
-		} else if c.Scheme == auth.BasicAuth {
+		case auth.BasicAuth:
 			sessionID, username, secret, err := a.getCredentials(host)
 			if err != nil {
 				return err
@@ -377,7 +378,7 @@ func (ah *authHandler) fetchToken(ctx context.Context, sm *session.Manager, g se
 				// retry with POST request
 				// As of September 2017, GCR is known to return 404.
 				// As of February 2018, JFrog Artifactory is known to return 401.
-				if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
+				if (errStatus.StatusCode == http.StatusMethodNotAllowed && to.Username != "") || errStatus.StatusCode == http.StatusNotFound || errStatus.StatusCode == http.StatusUnauthorized {
 					resp, err := auth.FetchTokenWithOAuth(ctx, ah.client, hdr, "buildkit-client", to)
 					if err != nil {
 						return nil, err
diff --git a/util/stack/stack.go b/util/stack/stack.go
index 458a1a781..d9bacd410 100644
--- a/util/stack/stack.go
+++ b/util/stack/stack.go
@@ -50,7 +50,7 @@ func Traces(err error) []*Stack {
 func traces(err error) []*Stack {
 	var st []*Stack
 
-	switch e := err.(type) {
+	switch e := err.(type) { //nolint:errorlint
 	case interface{ Unwrap() error }:
 		st = Traces(e.Unwrap())
 	case interface{ Unwrap() []error }:
@@ -63,7 +63,7 @@ func traces(err error) []*Stack {
 		}
 	}
 
-	switch ste := err.(type) {
+	switch ste := err.(type) { //nolint:errorlint
 	case interface{ StackTrace() errors.StackTrace }:
 		st = append(st, convertStack(ste.StackTrace()))
 	case interface{ StackTrace() *Stack }:
@@ -85,7 +85,7 @@ func Enable(err error) error {
 }
 
 func Wrap(err error, s *Stack) error {
-	return &withStack{stack: s, error: err}
+	return &withStackError{stack: s, error: err}
 }
 
 func hasLocalStackTrace(err error) bool {
@@ -173,15 +173,15 @@ func convertStack(s errors.StackTrace) *Stack {
 	return &out
 }
 
-type withStack struct {
+type withStackError struct {
 	stack *Stack
 	error
 }
 
-func (e *withStack) Unwrap() error {
+func (e *withStackError) Unwrap() error {
 	return e.error
 }
 
-func (e *withStack) StackTrace() *Stack {
+func (e *withStackError) StackTrace() *Stack {
 	return e.stack
 }
diff --git a/util/staticfs/merge.go b/util/staticfs/merge.go
index c5a582a5f..836978fc4 100644
--- a/util/staticfs/merge.go
+++ b/util/staticfs/merge.go
@@ -69,10 +69,7 @@ func (mfs *MergeFS) Walk(ctx context.Context, target string, fn fs.WalkDirFunc)
 		next2, ok2 := <-ch2
 		key2 := next2.key()
 
-		for {
-			if !ok1 && !ok2 {
-				break
-			}
+		for ok1 || ok2 {
 			if !ok2 || ok1 && key1 < key2 {
 				if err := fn(next1.path, next1.entry, next1.err); err != nil {
 					return err
diff --git a/util/tracing/otlptracegrpc/client.go b/util/tracing/otlptracegrpc/client.go
index 5e15772d5..843e82613 100644
--- a/util/tracing/otlptracegrpc/client.go
+++ b/util/tracing/otlptracegrpc/client.go
@@ -72,7 +72,7 @@ func (c *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
 	ctx, cancel := c.connection.ContextWithStop(ctx)
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 	ctx, tCancel := context.WithCancelCause(ctx)
-	ctx, _ = context.WithTimeoutCause(ctx, 30*time.Second, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, 30*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer tCancel(errors.WithStack(context.Canceled))
 
 	ctx = c.connection.ContextWithMetadata(ctx)
diff --git a/util/tracing/tracing.go b/util/tracing/tracing.go
index 038a7a17a..0d4fed97f 100644
--- a/util/tracing/tracing.go
+++ b/util/tracing/tracing.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptrace"
-	"slices"
 
 	"github.com/moby/buildkit/util/bklog"
 	"github.com/moby/buildkit/util/stack"
@@ -34,19 +33,9 @@ func StartSpan(ctx context.Context, operationName string, opts ...trace.SpanStar
 }
 
 func hasStacktrace(err error) bool {
-	switch e := err.(type) {
-	case interface{ StackTrace() *stack.Stack }:
-		return true
-	case interface{ StackTrace() errors.StackTrace }:
-		return true
-	case interface{ Unwrap() error }:
-		return hasStacktrace(e.Unwrap())
-	case interface{ Unwrap() []error }:
-		if slices.ContainsFunc(e.Unwrap(), hasStacktrace) {
-			return true
-		}
-	}
-	return false
+	var stack interface{ StackTrace() *stack.Stack }
+	var pkgStack interface{ StackTrace() errors.StackTrace }
+	return errors.As(err, &stack) || errors.As(err, &pkgStack)
 }
 
 // FinishWithError finalizes the span and sets the error if one is passed



Test patch:
diff --git a/api/services/control/control_bench_test.go b/api/services/control/control_bench_test.go
index 2fe28e890..65595af8b 100644
--- a/api/services/control/control_bench_test.go
+++ b/api/services/control/control_bench_test.go
@@ -1,4 +1,4 @@
-package moby_buildkit_v1 //nolint:revive
+package moby_buildkit_v1 //nolint:revive,staticcheck
 
 import (
 	"testing"
diff --git a/cache/manager_test.go b/cache/manager_test.go
index cd5e763c0..fd03bab81 100644
--- a/cache/manager_test.go
+++ b/cache/manager_test.go
@@ -1464,7 +1464,7 @@ func getCompressor(w io.Writer, compressionType compression.Type, customized boo
 	case compression.Gzip:
 		if customized {
 			gz, _ := gzip.NewWriterLevel(w, gzip.NoCompression)
-			gz.Header.Comment = "hello"
+			gz.Comment = "hello"
 			gz.Close()
 		}
 		return gzip.NewWriter(w), nil
@@ -2788,7 +2788,7 @@ func mapToSystemTarBlob(t *testing.T, m map[string]string) ([]byte, ocispecs.Des
 	tr := tar.NewReader(bytes.NewReader(tarout))
 	for {
 		h, err := tr.Next()
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			break
 		}
 		if err != nil {
@@ -2807,7 +2807,7 @@ func mapToSystemTarBlob(t *testing.T, m map[string]string) ([]byte, ocispecs.Des
 		if err != nil {
 			return nil, ocispecs.Descriptor{}, err
 		}
-		if string(gotV) != string(v) {
+		if string(gotV) != v {
 			return nil, ocispecs.Descriptor{}, errors.Errorf("unexpected contents of %s", h.Name)
 		}
 	}
diff --git a/cache/remotecache/v1/chains_test.go b/cache/remotecache/v1/chains_test.go
index b9083d9f2..561fe1342 100644
--- a/cache/remotecache/v1/chains_test.go
+++ b/cache/remotecache/v1/chains_test.go
@@ -69,7 +69,7 @@ func TestSimpleMarshal(t *testing.T) {
 	cfg2, descPairs, err := cc.Marshal(context.TODO())
 	require.NoError(t, err)
 
-	require.EqualValues(t, cfg, cfg2)
+	require.Equal(t, cfg, cfg2)
 
 	// marshal roundtrip
 	dt, err := json.Marshal(cfg)
@@ -81,7 +81,7 @@ func TestSimpleMarshal(t *testing.T) {
 
 	cfg3, _, err := cc.Marshal(context.TODO())
 	require.NoError(t, err)
-	require.EqualValues(t, cfg, cfg3)
+	require.Equal(t, cfg, cfg3)
 
 	// add extra item
 	cc.Add(outputKey(dgst("bay"), 0))
diff --git a/client/build_test.go b/client/build_test.go
index 645905282..2198dce55 100644
--- a/client/build_test.go
+++ b/client/build_test.go
@@ -1485,11 +1485,11 @@ func testClientGatewayExecError(t *testing.T, sb integration.Sandbox) {
 				require.Len(t, se.InputIDs, tt.NumMounts)
 				require.Len(t, se.MountIDs, tt.NumMounts)
 
-				op := se.Solve.Op
+				op := se.Op
 				require.NotNil(t, op)
 				require.NotNil(t, op.Op)
 
-				opExec, ok := se.Solve.Op.Op.(*pb.Op_Exec)
+				opExec, ok := se.Op.Op.(*pb.Op_Exec)
 				require.True(t, ok)
 
 				exec := opExec.Exec
@@ -1499,7 +1499,7 @@ func testClientGatewayExecError(t *testing.T, sb integration.Sandbox) {
 					mounts = append(mounts, client.Mount{
 						Selector:  mnt.Selector,
 						Dest:      mnt.Dest,
-						ResultID:  se.Solve.MountIDs[i],
+						ResultID:  se.MountIDs[i],
 						Readonly:  mnt.Readonly,
 						MountType: mnt.MountType,
 						CacheOpt:  mnt.CacheOpt,
@@ -1603,14 +1603,14 @@ func testClientGatewaySlowCacheExecError(t *testing.T, sb integration.Sandbox) {
 		var se *errdefs.SolveError
 		require.ErrorAs(t, solveErr, &se)
 
-		_, ok := se.Solve.Op.Op.(*pb.Op_Exec)
+		_, ok := se.Op.Op.(*pb.Op_Exec)
 		require.True(t, ok)
 
-		_, ok = se.Solve.Subject.(*errdefs.Solve_Cache)
+		_, ok = se.Subject.(*errdefs.Solve_Cache)
 		require.True(t, ok)
 		// Slow cache errors should only have exactly one input and no outputs.
-		require.Len(t, se.Solve.InputIDs, 1)
-		require.Len(t, se.Solve.MountIDs, 0)
+		require.Len(t, se.InputIDs, 1)
+		require.Len(t, se.MountIDs, 0)
 
 		st := llb.Image("busybox:latest")
 		def, err := st.Marshal(ctx)
@@ -1632,7 +1632,7 @@ func testClientGatewaySlowCacheExecError(t *testing.T, sb integration.Sandbox) {
 			}, {
 				Dest:      "/problem",
 				MountType: pb.MountType_BIND,
-				ResultID:  se.Solve.InputIDs[0],
+				ResultID:  se.InputIDs[0],
 			}},
 		})
 		require.NoError(t, err)
@@ -1735,15 +1735,15 @@ func testClientGatewayExecFileActionError(t *testing.T, sb integration.Sandbox)
 
 				var se *errdefs.SolveError
 				require.ErrorAs(t, err, &se)
-				require.Len(t, se.Solve.InputIDs, tt.NumInputs)
+				require.Len(t, se.InputIDs, tt.NumInputs)
 
 				// There is one output for every action in the fileop that failed.
-				require.Len(t, se.Solve.MountIDs, tt.NumOutputs)
+				require.Len(t, se.MountIDs, tt.NumOutputs)
 
-				op, ok := se.Solve.Op.Op.(*pb.Op_File)
+				op, ok := se.Op.Op.(*pb.Op_File)
 				require.True(t, ok)
 
-				subject, ok := se.Solve.Subject.(*errdefs.Solve_File)
+				subject, ok := se.Subject.(*errdefs.Solve_File)
 				require.True(t, ok)
 
 				// Retrieve the action that failed from the sbuject.
diff --git a/client/client_test.go b/client/client_test.go
index 666327101..f95055c69 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -557,7 +557,7 @@ func testExportedImageLabels(t *testing.T, sb integration.Sandbox) {
 
 	for {
 		resp, err := cl.Recv()
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			break
 		}
 		require.NoError(t, err)
@@ -3332,7 +3332,7 @@ func testUser(t *testing.T, sb integration.Sandbox) {
 	dt, err = os.ReadFile(filepath.Join(destDir, "root_supplementary"))
 	require.NoError(t, err)
 	require.True(t, strings.HasPrefix(string(dt), "root "))
-	require.True(t, strings.Contains(string(dt), "wheel"))
+	require.Contains(t, string(dt), "wheel")
 
 	dt2, err := os.ReadFile(filepath.Join(destDir, "default_supplementary"))
 	require.NoError(t, err)
@@ -5249,7 +5249,7 @@ func testStargzLazyRegistryCacheImportExport(t *testing.T, sb integration.Sandbo
 	require.NoError(t, err)
 
 	require.Equal(t, dgst, dgst2)
-	require.EqualValues(t, unique, unique2)
+	require.Equal(t, unique, unique2)
 
 	// clear all local state out
 	err = imageService.Delete(ctx, img.Name, images.SynchronousDelete())
@@ -5569,7 +5569,7 @@ func testStargzLazyPull(t *testing.T, sb integration.Sandbox) {
 	require.NoError(t, err)
 
 	require.Equal(t, dgst, dgst2)
-	require.EqualValues(t, unique, unique2)
+	require.Equal(t, unique, unique2)
 
 	// clear all local state out
 	err = imageService.Delete(ctx, img.Name, images.SynchronousDelete())
@@ -6423,7 +6423,7 @@ func testBasicInlineCacheImportExport(t *testing.T, sb integration.Sandbox) {
 	// dgst2uncompress != dgst, because the compression type is different
 	unique2uncompress, err := readFileInImage(sb.Context(), t, c, target+"@"+dgst2uncompress, "/unique")
 	require.NoError(t, err)
-	require.EqualValues(t, unique, unique2uncompress)
+	require.Equal(t, unique, unique2uncompress)
 
 	ensurePruneAll(t, c, sb)
 
@@ -6454,7 +6454,7 @@ func testBasicInlineCacheImportExport(t *testing.T, sb integration.Sandbox) {
 	// dgst3 != dgst, because inline cache is not exported for dgst3
 	unique3, err := readFileInImage(sb.Context(), t, c, target+"@"+dgst3, "/unique")
 	require.NoError(t, err)
-	require.EqualValues(t, unique, unique3)
+	require.Equal(t, unique, unique3)
 }
 
 func testRegistryEmptyCacheExport(t *testing.T, sb integration.Sandbox) {
@@ -7932,7 +7932,7 @@ func testMergeOpCache(t *testing.T, sb integration.Sandbox, mode string) {
 			},
 		}}
 	default:
-		require.Fail(t, "unknown cache mode: %s", mode)
+		require.Fail(t, fmt.Sprintf("unknown cache mode: %s", mode))
 	}
 
 	_, err = c.Solve(sb.Context(), def, SolveOpt{
@@ -8061,7 +8061,7 @@ func testMergeOpCache(t *testing.T, sb integration.Sandbox, mode string) {
 			_, err = contentStore.Info(ctx, layer.Digest)
 			require.NoError(t, err)
 		default:
-			require.Fail(t, "unexpected layer index %d", i)
+			require.Fail(t, fmt.Sprintf("unexpected layer index %d", i))
 		}
 	}
 
@@ -8302,7 +8302,7 @@ func checkAllReleasable(t *testing.T, c *Client, sb integration.Sandbox, checkCo
 
 	for {
 		resp, err := cl.Recv()
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			break
 		}
 		require.NoError(t, err)
@@ -11423,8 +11423,8 @@ func testLLBMountPerformance(t *testing.T, sb integration.Sandbox) {
 	require.NoError(t, err)
 
 	// Windows images take longer time
-	factor := integration.UnixOrWindows(time.Duration(1), time.Duration(3))
-	timeoutCtx, cancel := context.WithTimeoutCause(sb.Context(), time.Minute*factor, nil)
+	timeout := integration.UnixOrWindows(time.Minute, 3*time.Minute)
+	timeoutCtx, cancel := context.WithTimeoutCause(sb.Context(), timeout, nil)
 	defer cancel()
 	_, err = c.Solve(timeoutCtx, def, SolveOpt{}, nil)
 	require.NoError(t, err)
diff --git a/client/connhelper/dockercontainer/dockercontainer_test.go b/client/connhelper/dockercontainer/dockercontainer_test.go
index 33bcc4ecd..6902030b5 100644
--- a/client/connhelper/dockercontainer/dockercontainer_test.go
+++ b/client/connhelper/dockercontainer/dockercontainer_test.go
@@ -25,7 +25,7 @@ func TestSpecFromURL(t *testing.T) {
 		got, err := SpecFromURL(u)
 		if expected != nil {
 			require.NoError(t, err)
-			require.EqualValues(t, expected, got, s)
+			require.Equal(t, expected, got, s)
 		} else {
 			require.Error(t, err, s)
 		}
diff --git a/client/connhelper/kubepod/kubepod_test.go b/client/connhelper/kubepod/kubepod_test.go
index d7f3e89f0..224ff8656 100644
--- a/client/connhelper/kubepod/kubepod_test.go
+++ b/client/connhelper/kubepod/kubepod_test.go
@@ -31,7 +31,7 @@ func TestSpecFromURL(t *testing.T) {
 		got, err := SpecFromURL(u)
 		if expected != nil {
 			require.NoError(t, err)
-			require.EqualValues(t, expected, got, s)
+			require.Equal(t, expected, got, s)
 		} else {
 			require.Error(t, err, s)
 		}
diff --git a/client/connhelper/nerdctlcontainer/nerdctlcontainer_test.go b/client/connhelper/nerdctlcontainer/nerdctlcontainer_test.go
index c8db4b21e..c2805248b 100644
--- a/client/connhelper/nerdctlcontainer/nerdctlcontainer_test.go
+++ b/client/connhelper/nerdctlcontainer/nerdctlcontainer_test.go
@@ -22,7 +22,7 @@ func TestSpecFromURL(t *testing.T) {
 		got, err := SpecFromURL(u)
 		if expected != nil {
 			require.NoError(t, err)
-			require.EqualValues(t, expected, got, s)
+			require.Equal(t, expected, got, s)
 		} else {
 			require.Error(t, err, s)
 		}
diff --git a/client/connhelper/podmancontainer/podmancontainer_test.go b/client/connhelper/podmancontainer/podmancontainer_test.go
index fbc6e1e07..a19fae14d 100644
--- a/client/connhelper/podmancontainer/podmancontainer_test.go
+++ b/client/connhelper/podmancontainer/podmancontainer_test.go
@@ -22,7 +22,7 @@ func TestSpecFromURL(t *testing.T) {
 		got, err := SpecFromURL(u)
 		if expected != nil {
 			require.NoError(t, err)
-			require.EqualValues(t, expected, got, s)
+			require.Equal(t, expected, got, s)
 		} else {
 			require.Error(t, err, s)
 		}
diff --git a/client/connhelper/ssh/ssh_test.go b/client/connhelper/ssh/ssh_test.go
index e4afb31cf..96ebdbefe 100644
--- a/client/connhelper/ssh/ssh_test.go
+++ b/client/connhelper/ssh/ssh_test.go
@@ -31,7 +31,7 @@ func TestSpecFromURL(t *testing.T) {
 		got, err := SpecFromURL(u)
 		if expected != nil {
 			require.NoError(t, err)
-			require.EqualValues(t, expected, got, s)
+			require.Equal(t, expected, got, s)
 		} else {
 			require.Error(t, err, s)
 		}
diff --git a/cmd/buildctl/build/exportcache_test.go b/cmd/buildctl/build/exportcache_test.go
index ccaa32173..c332a0e89 100644
--- a/cmd/buildctl/build/exportcache_test.go
+++ b/cmd/buildctl/build/exportcache_test.go
@@ -44,7 +44,7 @@ func TestParseExportCache(t *testing.T) {
 	for _, tc := range testCases {
 		ex, err := ParseExportCache(tc.exportCaches)
 		if tc.expectedErr == "" {
-			require.EqualValues(t, tc.expected, ex)
+			require.Equal(t, tc.expected, ex)
 		} else {
 			require.Error(t, err)
 			require.Contains(t, err.Error(), tc.expectedErr)
diff --git a/cmd/buildctl/build/importcache_test.go b/cmd/buildctl/build/importcache_test.go
index bc8c10560..e53a0c7ed 100644
--- a/cmd/buildctl/build/importcache_test.go
+++ b/cmd/buildctl/build/importcache_test.go
@@ -98,7 +98,7 @@ func TestParseImportCache(t *testing.T) {
 	for _, tc := range testCases {
 		im, err := ParseImportCache(tc.importCaches)
 		if tc.expectedErr == "" {
-			require.EqualValues(t, tc.expected, im)
+			require.Equal(t, tc.expected, im)
 		} else {
 			require.Error(t, err)
 			require.Contains(t, err.Error(), tc.expectedErr)
diff --git a/cmd/buildctl/build/registryauthtlscontext_test.go b/cmd/buildctl/build/registryauthtlscontext_test.go
index 06822eea9..5ab809434 100644
--- a/cmd/buildctl/build/registryauthtlscontext_test.go
+++ b/cmd/buildctl/build/registryauthtlscontext_test.go
@@ -100,7 +100,7 @@ func TestParseRegistryAuthTLSContext(t *testing.T) {
 	for _, tc := range testCases {
 		im, err := ParseRegistryAuthTLSContext(tc.registryAuthTLSContext)
 		if tc.expectedErr == "" {
-			require.EqualValues(t, tc.expected, im)
+			require.Equal(t, tc.expected, im)
 		} else {
 			require.Error(t, err)
 			require.Contains(t, err.Error(), tc.expectedErr)
diff --git a/exporter/attestation/make.go b/exporter/attestation/make.go
index d982f798b..13c2df520 100644
--- a/exporter/attestation/make.go
+++ b/exporter/attestation/make.go
@@ -20,7 +20,7 @@ import (
 func ReadAll(ctx context.Context, s session.Group, att exporter.Attestation) ([]byte, error) {
 	var content []byte
 	if att.ContentFunc != nil {
-		data, err := att.ContentFunc()
+		data, err := att.ContentFunc(ctx)
 		if err != nil {
 			return nil, err
 		}
diff --git a/exporter/attestation/unbundle.go b/exporter/attestation/unbundle.go
index 49ec61bca..d68a2a5b2 100644
--- a/exporter/attestation/unbundle.go
+++ b/exporter/attestation/unbundle.go
@@ -166,7 +166,7 @@ func unbundle(root string, bundle exporter.Attestation) ([]exporter.Attestation,
 			Kind:        gatewaypb.AttestationKind_InToto,
 			Metadata:    bundle.Metadata,
 			Path:        path.Join(bundle.Path, entry.Name()),
-			ContentFunc: func() ([]byte, error) { return predicate, nil },
+			ContentFunc: func(context.Context) ([]byte, error) { return predicate, nil },
 			InToto: result.InTotoAttestation{
 				PredicateType: stmt.PredicateType,
 				Subjects:      subjects,
diff --git a/exporter/containerimage/attestations.go b/exporter/containerimage/attestations.go
index bea8c0c0b..8d6928473 100644
--- a/exporter/containerimage/attestations.go
+++ b/exporter/containerimage/attestations.go
@@ -118,7 +118,7 @@ func supplementSBOM(ctx context.Context, s session.Group, target cache.Immutable
 	return exporter.Attestation{
 		Kind:        att.Kind,
 		Path:        att.Path,
-		ContentFunc: func() ([]byte, error) { return content, nil },
+		ContentFunc: func(context.Context) ([]byte, error) { return content, nil },
 		InToto:      att.InToto,
 	}, nil
 }
diff --git a/frontend/dockerfile/dockerfile_heredoc_test.go b/frontend/dockerfile/dockerfile_heredoc_test.go
index 6f48082dc..22fb78ddc 100644
--- a/frontend/dockerfile/dockerfile_heredoc_test.go
+++ b/frontend/dockerfile/dockerfile_heredoc_test.go
@@ -72,7 +72,7 @@ COPY --from=build /dest /
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -143,7 +143,7 @@ EOF
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -213,7 +213,7 @@ COPY --from=build /dest /dest
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -261,7 +261,7 @@ COPY --from=build /dest /dest
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -310,7 +310,7 @@ COPY --from=build /dest /dest
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -373,7 +373,7 @@ COPY --from=build /dest /
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -463,7 +463,7 @@ COPY --from=build /dest /
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -557,7 +557,7 @@ COPY --from=build /dest /
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
diff --git a/frontend/dockerfile/dockerfile_outline_test.go b/frontend/dockerfile/dockerfile_outline_test.go
index 985ad66ac..630c47cab 100644
--- a/frontend/dockerfile/dockerfile_outline_test.go
+++ b/frontend/dockerfile/dockerfile_outline_test.go
@@ -92,7 +92,7 @@ FROM second
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -197,7 +197,7 @@ FROM second
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
@@ -293,7 +293,7 @@ ARG INFOO=${INFOO}456${INBAR}
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
diff --git a/frontend/dockerfile/dockerfile_runnetwork_test.go b/frontend/dockerfile/dockerfile_runnetwork_test.go
index e0ba322d0..b94260469 100644
--- a/frontend/dockerfile/dockerfile_runnetwork_test.go
+++ b/frontend/dockerfile/dockerfile_runnetwork_test.go
@@ -147,7 +147,7 @@ RUN --network=host nc 127.0.0.1 %s | grep foo
 			require.NoError(t, err)
 		}
 	default:
-		require.Fail(t, "unexpected network.host mode %q", hostAllowed)
+		require.Fail(t, fmt.Sprintf("unexpected network.host mode %q", hostAllowed))
 	}
 }
 
@@ -198,6 +198,6 @@ RUN --network=none ! nc -z 127.0.0.1 %s
 			require.NoError(t, err)
 		}
 	default:
-		require.Fail(t, "unexpected network.host mode %q", hostAllowed)
+		require.Fail(t, fmt.Sprintf("unexpected network.host mode %q", hostAllowed))
 	}
 }
diff --git a/frontend/dockerfile/dockerfile_targets_test.go b/frontend/dockerfile/dockerfile_targets_test.go
index daab40fd1..55cb9b0dc 100644
--- a/frontend/dockerfile/dockerfile_targets_test.go
+++ b/frontend/dockerfile/dockerfile_targets_test.go
@@ -49,7 +49,7 @@ FROM second AS binary
 
 	dir := integration.Tmpdir(
 		t,
-		fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600),
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 	)
 
 	c, err := client.New(sb.Context(), sb.Address())
diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go
index 4bb369026..ac47a37f4 100644
--- a/frontend/dockerfile/dockerfile_test.go
+++ b/frontend/dockerfile/dockerfile_test.go
@@ -234,6 +234,7 @@ var heredocTests = []integration.Test{}
 // Tests that depend on reproducible env
 var reproTests = integration.TestFuncs(
 	testReproSourceDateEpoch,
+	testWorkdirSourceDateEpochReproducible,
 )
 
 var (
@@ -910,6 +911,84 @@ WORKDIR /
 	require.Equal(t, true, fi.IsDir())
 }
 
+// testWorkdirSourceDateEpochReproducible ensures that WORKDIR is reproducible with SOURCE_DATE_EPOCH.
+func testWorkdirSourceDateEpochReproducible(t *testing.T, sb integration.Sandbox) {
+	integration.SkipOnPlatform(t, "windows")
+	workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter, workers.FeatureSourceDateEpoch)
+	f := getFrontend(t, sb)
+
+	dockerfile := []byte(`
+FROM alpine
+WORKDIR /mydir
+`)
+
+	dir := integration.Tmpdir(
+		t,
+		fstest.CreateFile("Dockerfile", dockerfile, 0600),
+	)
+
+	c, err := client.New(sb.Context(), sb.Address())
+	require.NoError(t, err)
+	defer c.Close()
+
+	destDir1 := t.TempDir()
+	epoch := fmt.Sprintf("%d", time.Date(2023, 1, 10, 15, 34, 56, 0, time.UTC).Unix())
+
+	_, err = f.Solve(sb.Context(), c, client.SolveOpt{
+		FrontendAttrs: map[string]string{
+			"build-arg:SOURCE_DATE_EPOCH": epoch,
+		},
+		Exports: []client.ExportEntry{
+			{
+				Type:      client.ExporterOCI,
+				OutputDir: destDir1,
+				Attrs: map[string]string{
+					"tar": "false",
+				},
+			},
+		},
+		LocalMounts: map[string]fsutil.FS{
+			dockerui.DefaultLocalNameDockerfile: dir,
+			dockerui.DefaultLocalNameContext:    dir,
+		},
+	}, nil)
+	require.NoError(t, err)
+
+	index1, err := os.ReadFile(filepath.Join(destDir1, "index.json"))
+	require.NoError(t, err)
+
+	// Prune all cache
+	ensurePruneAll(t, c, sb)
+
+	time.Sleep(3 * time.Second)
+
+	destDir2 := t.TempDir()
+	_, err = f.Solve(sb.Context(), c, client.SolveOpt{
+		FrontendAttrs: map[string]string{
+			"build-arg:SOURCE_DATE_EPOCH": epoch,
+		},
+		Exports: []client.ExportEntry{
+			{
+				Type:      client.ExporterOCI,
+				OutputDir: destDir2,
+				Attrs: map[string]string{
+					"tar": "false",
+				},
+			},
+		},
+		LocalMounts: map[string]fsutil.FS{
+			dockerui.DefaultLocalNameDockerfile: dir,
+			dockerui.DefaultLocalNameContext:    dir,
+		},
+	}, nil)
+	require.NoError(t, err)
+
+	index2, err := os.ReadFile(filepath.Join(destDir2, "index.json"))
+	require.NoError(t, err)
+
+	require.Equal(t, index1, index2)
+}
+
 func testCacheReleased(t *testing.T, sb integration.Sandbox) {
 	f := getFrontend(t, sb)
 
@@ -3628,7 +3707,7 @@ COPY . .
 	)
 
 	ctx, cancel := context.WithCancelCause(sb.Context())
-	ctx, _ = context.WithTimeoutCause(ctx, 15*time.Second, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, 15*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 
 	c, err := client.New(ctx, sb.Address())
@@ -7162,9 +7241,10 @@ COPY --from=base --chmod=0644 /out /out
 				}
 				visited[vtx.Name] = struct{}{}
 				t.Logf("step: %q", vtx.Name)
-				if vtx.Name == `[base 3/3] RUN echo "base" > base` {
+				switch vtx.Name {
+				case `[base 3/3] RUN echo "base" > base`:
 					hasRun = true
-				} else if vtx.Name == `[stage-1 1/1] COPY --from=base --chmod=0644 /out /out` {
+				case `[stage-1 1/1] COPY --from=base --chmod=0644 /out /out`:
 					hasCopy = true
 				}
 			}
@@ -9418,7 +9498,7 @@ COPY notexist /foo
 	got := false
 	for {
 		resp, err := cl.Recv()
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			require.Equal(t, true, got, "expected error was %+v", expectedError)
 			break
 		}
@@ -9460,7 +9540,7 @@ COPY notexist /foo
 		}
 
 		err = grpcerrors.FromGRPC(status.FromProto(&statuspb.Status{
-			Code:    int32(st.Code),
+			Code:    st.Code,
 			Message: st.Message,
 			Details: details,
 		}).Err())
@@ -9542,7 +9622,7 @@ COPY Dockerfile /foo
 	got := false
 	for {
 		resp, err := cl.Recv()
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			require.Equal(t, true, got)
 			break
 		}
@@ -9647,8 +9727,8 @@ EOF
 	info, err := testutil.ReadImages(ctx, provider, desc)
 	require.NoError(t, err)
 	require.Len(t, info.Images, 2)
-	require.Equal(t, info.Images[0].Img.Platform.OSVersion, p1.OSVersion)
-	require.Equal(t, info.Images[1].Img.Platform.OSVersion, p2.OSVersion)
+	require.Equal(t, info.Images[0].Img.OSVersion, p1.OSVersion)
+	require.Equal(t, info.Images[1].Img.OSVersion, p2.OSVersion)
 
 	dt, err := os.ReadFile(filepath.Join(destDir, strings.Replace(p1Str, "/", "_", 1), "osversion"))
 	require.NoError(t, err)
@@ -9785,7 +9865,7 @@ EOF
 	info, err := testutil.ReadImages(ctx, provider, desc)
 	require.NoError(t, err)
 	require.Len(t, info.Images, 1)
-	require.Equal(t, info.Images[0].Img.Platform.OSVersion, p1.OSVersion)
+	require.Equal(t, info.Images[0].Img.OSVersion, p1.OSVersion)
 
 	dockerfile = fmt.Appendf(nil, `
 FROM %s
@@ -9828,7 +9908,7 @@ EOF
 	info, err = testutil.ReadImages(ctx, provider, desc)
 	require.NoError(t, err)
 	require.Len(t, info.Images, 1)
-	require.Equal(t, info.Images[0].Img.Platform.OSVersion, p1.OSVersion)
+	require.Equal(t, info.Images[0].Img.OSVersion, p1.OSVersion)
 }
 
 func testTargetMistype(t *testing.T, sb integration.Sandbox) {
@@ -9915,7 +9995,7 @@ func checkAllReleasable(t *testing.T, c *client.Client, sb integration.Sandbox,
 
 	for {
 		resp, err := cl.Recv()
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			break
 		}
 		require.NoError(t, err)
diff --git a/frontend/dockerfile/parser/json_test.go b/frontend/dockerfile/parser/json_test.go
index 14dcdcfcd..498d21599 100644
--- a/frontend/dockerfile/parser/json_test.go
+++ b/frontend/dockerfile/parser/json_test.go
@@ -2,6 +2,8 @@ package parser
 
 import (
 	"testing"
+
+	"github.com/pkg/errors"
 )
 
 var invalidJSONArraysOfStrings = []string{
@@ -48,7 +50,7 @@ func TestJSONArraysOfStrings(t *testing.T) {
 		}
 	}
 	for _, json := range invalidJSONArraysOfStrings {
-		if _, _, err := parseJSON(json); err != errDockerfileNotStringArray {
+		if _, _, err := parseJSON(json); !errors.Is(err, errDockerfileNotStringArray) {
 			t.Fatalf("%q should be an invalid JSON array of strings, but wasn't!", json)
 		}
 	}
diff --git a/snapshot/snapshotter_test.go b/snapshot/snapshotter_test.go
index 60bff57d9..a9cb00816 100644
--- a/snapshot/snapshotter_test.go
+++ b/snapshot/snapshotter_test.go
@@ -353,10 +353,10 @@ func TestHardlinks(t *testing.T) {
 			)
 			stat1 = statPath(ctx, t, sn, childSnap.Name, "1")
 			require.EqualValues(t, 1, stat1.Nlink)
-			require.NotEqualValues(t, stat1Ino, stat1.Ino)
+			require.NotEqual(t, stat1Ino, stat1.Ino)
 			stat2 = statPath(ctx, t, sn, childSnap.Name, "2")
 			require.EqualValues(t, 1, stat2.Nlink)
-			require.NotEqualValues(t, stat2Ino, stat2.Ino)
+			require.NotEqual(t, stat2Ino, stat2.Ino)
 
 			// verify the original files and the files inthe merge are unchanged
 			requireContents(ctx, t, sn, base1Snap.Name,
diff --git a/solver/jobs_test.go b/solver/jobs_test.go
index 7abf2da06..ba5d1835a 100644
--- a/solver/jobs_test.go
+++ b/solver/jobs_test.go
@@ -80,9 +80,10 @@ func testParallelism(t *testing.T, sb integration.Sandbox) {
 	elapsed := time.Since(timeStart)
 
 	maxParallelism := sb.Value("max-parallelism")
-	if maxParallelism == maxParallelismSingle {
+	switch maxParallelism {
+	case maxParallelismSingle:
 		require.Greater(t, elapsed, 10*time.Second, "parallelism not restricted")
-	} else if maxParallelism == maxParallelismUnlimited {
+	case maxParallelismUnlimited:
 		require.Less(t, elapsed, 10*time.Second, "parallelism hindered")
 	}
 }
diff --git a/solver/result/attestation.go b/solver/result/attestation.go
index 2fee27824..de56e3c40 100644
--- a/solver/result/attestation.go
+++ b/solver/result/attestation.go
@@ -1,6 +1,8 @@
 package result
 
 import (
+	"context"
+
 	pb "github.com/moby/buildkit/frontend/gateway/pb"
 	digest "github.com/opencontainers/go-digest"
 )
@@ -23,7 +25,7 @@ type Attestation[T any] struct {
 
 	Ref         T
 	Path        string
-	ContentFunc func() ([]byte, error)
+	ContentFunc func(context.Context) ([]byte, error)
 
 	InToto InTotoAttestation
 }
diff --git a/solver/testutil/cachestorage_testsuite.go b/solver/testutil/cachestorage_testsuite.go
index 3ac5afc41..eef838ef5 100644
--- a/solver/testutil/cachestorage_testsuite.go
+++ b/solver/testutil/cachestorage_testsuite.go
@@ -44,7 +44,7 @@ func testResults(t *testing.T, st solver.CacheKeyStorage) {
 
 	// Windows time.Now() resolution can be quite coarse, so frequently
 	// time.Now() will be the same between two nearby calls.
-	if time.Now() == timeNow {
+	if time.Now().Equal(timeNow) {
 		time.Sleep(time.Duration(100) * time.Millisecond)
 	}
 	require.NotEqual(t, timeNow, time.Now(), "time has stopped")
@@ -211,7 +211,7 @@ func testResultReleaseSingleLevel(t *testing.T, st solver.CacheKeyStorage) {
 	require.Equal(t, 0, len(m))
 
 	st.Walk(func(id string) error {
-		require.False(t, true, fmt.Sprintf("id %s should have been released", id))
+		require.Fail(t, fmt.Sprintf("id %s should have been released", id))
 		return nil
 	})
 }
@@ -339,7 +339,7 @@ func testResultReleaseMultiLevel(t *testing.T, st solver.CacheKeyStorage) {
 	require.False(t, st.Exists("foo"))
 
 	st.Walk(func(id string) error {
-		require.False(t, true, fmt.Sprintf("id %s should have been released", id))
+		require.Fail(t, fmt.Sprintf("id %s should have been released", id))
 		return nil
 	})
 }
diff --git a/source/git/source_test.go b/source/git/source_test.go
index bdb765330..5962814af 100644
--- a/source/git/source_test.go
+++ b/source/git/source_test.go
@@ -673,7 +673,7 @@ func TestCredentialRedaction(t *testing.T) {
 
 	_, _, _, _, err = g.CacheKey(ctx, nil, 0)
 	require.Error(t, err)
-	require.False(t, strings.Contains(err.Error(), "keepthissecret"))
+	require.NotContains(t, err.Error(), "keepthissecret")
 }
 
 func TestSubdir(t *testing.T) {
diff --git a/sourcepolicy/pb/json_test.go b/sourcepolicy/pb/json_test.go
index a590763c3..25c19c048 100644
--- a/sourcepolicy/pb/json_test.go
+++ b/sourcepolicy/pb/json_test.go
@@ -1,4 +1,4 @@
-package moby_buildkit_v1_sourcepolicy //nolint:revive
+package moby_buildkit_v1_sourcepolicy //nolint:revive,staticcheck
 
 import (
 	"encoding/json"
diff --git a/util/grpcerrors/grpcerrors_test.go b/util/grpcerrors/grpcerrors_test.go
index c6a7c0ee1..241127f37 100644
--- a/util/grpcerrors/grpcerrors_test.go
+++ b/util/grpcerrors/grpcerrors_test.go
@@ -38,7 +38,7 @@ func TestFromGRPCPreserveUnknownTypes(t *testing.T) {
 
 	assertErrorProperties := func(t *testing.T, err error) {
 		require.Error(t, err)
-		assert.Equal(t, fmt.Sprintf("%s: %s", codes.Code(errCode), errMessage), err.Error())
+		assert.Equal(t, fmt.Sprintf("%s: %s", errCode, errMessage), err.Error())
 
 		st, ok := status.FromError(err)
 		require.True(t, ok)
diff --git a/util/imageutil/config_test.go b/util/imageutil/config_test.go
index 3c91ae3a0..3c6af1f66 100644
--- a/util/imageutil/config_test.go
+++ b/util/imageutil/config_test.go
@@ -193,7 +193,7 @@ type raReader struct {
 }
 
 func (r *raReader) Read(p []byte) (int, error) {
-	n, err := r.ReaderAt.ReadAt(p, int64(r.pos))
+	n, err := r.ReadAt(p, int64(r.pos))
 	r.pos += n
 	return n, err
 }
diff --git a/util/progress/progress_test.go b/util/progress/progress_test.go
index 2ce9421a4..36dce419c 100644
--- a/util/progress/progress_test.go
+++ b/util/progress/progress_test.go
@@ -126,7 +126,7 @@ func saveProgress(ctx context.Context, pr Reader, t *trace) error {
 	for {
 		p, err := pr.Read(ctx)
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				return nil
 			}
 			return err
diff --git a/util/testutil/dockerd/client/request.go b/util/testutil/dockerd/client/request.go
index 47dc9ec06..1b81704a6 100644
--- a/util/testutil/dockerd/client/request.go
+++ b/util/testutil/dockerd/client/request.go
@@ -52,15 +52,18 @@ func (cli *Client) doRequest(req *http.Request) (*http.Response, error) {
 			return nil, err
 		}
 
-		if uErr, ok := err.(*url.Error); ok {
-			if nErr, ok := uErr.Err.(*net.OpError); ok {
+		uErr := &url.Error{}
+		if errors.As(err, &uErr) {
+			nErr := &net.OpError{}
+			if errors.As(uErr.Err, &nErr) {
 				if os.IsPermission(nErr.Err) {
 					return nil, errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)
 				}
 			}
 		}
 
-		if nErr, ok := err.(net.Error); ok {
+		var nErr net.Error
+		if errors.As(err, &nErr) {
 			// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
 			if nErr.Timeout() {
 				return nil, ErrorConnectionFailed(cli.host)
diff --git a/util/testutil/dockerd/daemon.go b/util/testutil/dockerd/daemon.go
index c2523adf3..fd7cd21ce 100644
--- a/util/testutil/dockerd/daemon.go
+++ b/util/testutil/dockerd/daemon.go
@@ -72,7 +72,7 @@ func NewDaemon(workingDir string, ops ...Option) (*Daemon, error) {
 		execRoot:      filepath.Join(os.TempDir(), "dxr", id),
 		dockerdBinary: DefaultDockerdBinary,
 		Log:           nopLog{},
-		sockPath:      filepath.Join(sockRoot, id+".sock"),
+		sockPath:      getDockerdSockPath(sockRoot, id),
 		envs:          os.Environ(),
 	}
 
@@ -96,7 +96,7 @@ func WithExtraEnv(envs []string) Option {
 }
 
 func (d *Daemon) Sock() string {
-	return "unix://" + d.sockPath
+	return socketScheme + d.sockPath
 }
 
 func (d *Daemon) StartWithError(daemonLogs map[string]*bytes.Buffer, providedArgs ...string) error {
diff --git a/util/testutil/dockerd/daemon_unix.go b/util/testutil/dockerd/daemon_unix.go
new file mode 100644
index 000000000..ad1514ebc
--- /dev/null
+++ b/util/testutil/dockerd/daemon_unix.go
@@ -0,0 +1,11 @@
+//go:build !windows
+
+package dockerd
+
+import "path/filepath"
+
+const socketScheme = "unix://"
+
+func getDockerdSockPath(sockRoot, id string) string {
+	return filepath.Join(sockRoot, id+".sock")
+}
diff --git a/util/testutil/dockerd/daemon_windows.go b/util/testutil/dockerd/daemon_windows.go
new file mode 100644
index 000000000..c281b742a
--- /dev/null
+++ b/util/testutil/dockerd/daemon_windows.go
@@ -0,0 +1,7 @@
+package dockerd
+
+const socketScheme = "npipe://"
+
+func getDockerdSockPath(_, id string) string {
+	return `//./pipe/dockerd-` + id
+}
diff --git a/util/testutil/helpers/azurite.go b/util/testutil/helpers/azurite.go
index 26bc460e5..cbaaf024c 100644
--- a/util/testutil/helpers/azurite.go
+++ b/util/testutil/helpers/azurite.go
@@ -77,7 +77,7 @@ func waitAzurite(ctx context.Context, address string, d time.Duration) error {
 	step := 1 * time.Second
 	i := 0
 	for {
-		req, err := http.NewRequest("GET", fmt.Sprintf("%s?comp=list", address), nil)
+		req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s?comp=list", address), nil)
 		if err != nil {
 			return errors.Wrapf(err, "failed to create request")
 		}
diff --git a/util/testutil/helpers/minio.go b/util/testutil/helpers/minio.go
index 2c2f2c800..f3070c1d5 100644
--- a/util/testutil/helpers/minio.go
+++ b/util/testutil/helpers/minio.go
@@ -105,7 +105,7 @@ func waitMinio(ctx context.Context, address string, d time.Duration) error {
 	step := 1 * time.Second
 	i := 0
 	for {
-		req, err := http.NewRequest("GET", fmt.Sprintf("%s/minio/health/live", address), nil)
+		req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/minio/health/live", address), nil)
 		if err != nil {
 			return errors.Wrapf(err, "failed to create request")
 		}
diff --git a/util/testutil/integration/registry.go b/util/testutil/integration/registry.go
index 0f2152de5..ccb9a1fd6 100644
--- a/util/testutil/integration/registry.go
+++ b/util/testutil/integration/registry.go
@@ -68,7 +68,7 @@ http:
 	deferF.Append(stop)
 
 	ctx, cancel := context.WithCancelCause(context.Background())
-	ctx, _ = context.WithTimeoutCause(ctx, 5*time.Second, errors.WithStack(context.DeadlineExceeded))
+	ctx, _ = context.WithTimeoutCause(ctx, 5*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
 	defer func() { cancel(errors.WithStack(context.Canceled)) }()
 	url, err = detectPort(ctx, rc)
 	if err != nil {
diff --git a/util/testutil/tar.go b/util/testutil/tar.go
index a519026b6..94069e2bf 100644
--- a/util/testutil/tar.go
+++ b/util/testutil/tar.go
@@ -29,7 +29,7 @@ func ReadTarToMap(dt []byte, compressed bool) (map[string]*TarItem, error) {
 	for {
 		h, err := tr.Next()
 		if err != nil {
-			if err == io.EOF {
+			if errors.Is(err, io.EOF) {
 				return m, nil
 			}
 			return nil, errors.Wrap(err, "error reading tar")
diff --git a/util/testutil/workers/dockerd.go b/util/testutil/workers/dockerd.go
index ba557580e..2e84d4056 100644
--- a/util/testutil/workers/dockerd.go
+++ b/util/testutil/workers/dockerd.go
@@ -111,6 +111,7 @@ func (c Moby) New(ctx context.Context, cfg *integration.BackendConfig) (b integr
 			"containerd-snapshotter": c.ContainerdSnapshotter,
 		},
 	}
+
 	if reg, ok := bkcfg.Registries["docker.io"]; ok && len(reg.Mirrors) > 0 {
 		for _, m := range reg.Mirrors {
 			dcfg.Mirrors = append(dcfg.Mirrors, "http://"+m)
@@ -158,10 +159,13 @@ func (c Moby) New(ctx context.Context, cfg *integration.BackendConfig) (b integr
 
 	dockerdFlags := []string{
 		"--config-file", dockerdConfigFile,
-		"--userland-proxy=false",
 		"--tls=false",
 		"--debug",
 	}
+
+	// add platform-specific flags
+	dockerdFlags = applyDockerdPlatformFlags(dockerdFlags, c.ID)
+
 	if s := os.Getenv("BUILDKIT_INTEGRATION_DOCKERD_FLAGS"); s != "" {
 		dockerdFlags = append(dockerdFlags, strings.Split(strings.TrimSpace(s), "\n")...)
 	}
@@ -198,7 +202,7 @@ func (c Moby) New(ctx context.Context, cfg *integration.BackendConfig) (b integr
 	f.Close()
 	os.Remove(localPath)
 
-	listener, err := net.Listen("unix", localPath)
+	listener, err := net.Listen(buildkitdNetworkProtocol, getBuildkitdNetworkAddr(localPath))
 	if err != nil {
 		return nil, nil, errors.Wrapf(err, "dockerd listener error: %s", integration.FormatLogs(cfg.Logs))
 	}
@@ -234,7 +238,7 @@ func (c Moby) New(ctx context.Context, cfg *integration.BackendConfig) (b integr
 	})
 
 	return backend{
-		address:             "unix://" + listener.Addr().String(),
+		address:             buildkitdNetworkProtocol + "://" + listener.Addr().String(),
 		dockerAddress:       d.Sock(),
 		rootless:            c.IsRootless,
 		netnsDetached:       false,
diff --git a/util/testutil/workers/util_unix.go b/util/testutil/workers/util_unix.go
index 0b7d2d1be..12b2009f4 100644
--- a/util/testutil/workers/util_unix.go
+++ b/util/testutil/workers/util_unix.go
@@ -13,6 +13,8 @@ import (
 	"github.com/pkg/errors"
 )
 
+const buildkitdNetworkProtocol = "unix"
+
 func applyBuildkitdPlatformFlags(args []string) []string {
 	return append(args, "--oci-worker=false")
 }
@@ -75,3 +77,12 @@ func normalizeAddress(address string) string {
 	// for parity with windows, no effect for unix
 	return address
 }
+
+func applyDockerdPlatformFlags(flags []string, _ string) []string {
+	flags = append(flags, "--userland-proxy=false")
+	return flags
+}
+
+func getBuildkitdNetworkAddr(tmpdir string) string {
+	return tmpdir
+}
diff --git a/util/testutil/workers/util_windows.go b/util/testutil/workers/util_windows.go
index 336df47ab..f6ccbf486 100644
--- a/util/testutil/workers/util_windows.go
+++ b/util/testutil/workers/util_windows.go
@@ -4,8 +4,12 @@ import (
 	"path/filepath"
 	"strings"
 	"syscall"
+
+	"github.com/containerd/containerd/v2/defaults"
 )
 
+const buildkitdNetworkProtocol = "tcp"
+
 func applyBuildkitdPlatformFlags(args []string) []string {
 	return args
 }
@@ -55,3 +59,15 @@ func normalizeAddress(address string) string {
 	}
 	return address
 }
+
+func applyDockerdPlatformFlags(flags []string, workerID string) []string {
+	if workerID == "dockerd-containerd" {
+		flags = append(flags, "--default-runtime="+defaults.DefaultRuntime)
+	}
+	return flags
+}
+
+func getBuildkitdNetworkAddr(_ string) string {
+	// Using TCP on Windows, instead of Unix sockets.
+	return "localhost:0"
+}
diff --git a/util/throttle/throttle_test.go b/util/throttle/throttle_test.go
index be3d5ae92..fd9d013ae 100644
--- a/util/throttle/throttle_test.go
+++ b/util/throttle/throttle_test.go
@@ -29,9 +29,7 @@ func TestThrottle(t *testing.T) {
 		require.Less(t, retries, 10)
 		time.Sleep(60 * time.Millisecond)
 		v := atomic.LoadInt64(&i)
-		if v > 1 {
-			require.Fail(t, "invalid value %d", v)
-		}
+		require.LessOrEqual(t, v, int64(1))
 		if v == 1 {
 			break
 		}
diff --git a/worker/runc/runc_test.go b/worker/runc/runc_test.go
index 82b4c40f5..c1e610b6a 100644
--- a/worker/runc/runc_test.go
+++ b/worker/runc/runc_test.go
@@ -207,7 +207,7 @@ func TestRuncWorkerNoProcessSandbox(t *testing.T) {
 	stdout := bytes.NewBuffer(nil)
 	stderr := bytes.NewBuffer(nil)
 	_, err = w.WorkerOpt.Executor.Run(ctx, "", execMount(root, false), nil, executor.ProcessInfo{Meta: meta, Stdout: &nopCloser{stdout}, Stderr: &nopCloser{stderr}}, nil)
-	require.NoError(t, err, fmt.Sprintf("stdout=%q, stderr=%q", stdout.String(), stderr.String()))
+	require.NoError(t, err, "stdout=%q, stderr=%q", stdout.String(), stderr.String())
 	require.Equal(t, string(selfCmdline), stdout.String())
 }