From 7bf572b60268bff4e805f846adb02b46eaef4ed0 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 2 Apr 2026 22:41:33 +0200 Subject: [PATCH 1/4] fix QF1012 linting (staticcheck) util/desktop/desktop.go:44:4: QF1012: Use fmt.Fprintf(...) instead of WriteString(fmt.Sprintf(...)) (staticcheck) out.WriteString(fmt.Sprintf("\n %s: ", target)) ^ Signed-off-by: Sebastiaan van Stijn --- build/build.go | 4 ++-- commands/create.go | 2 +- util/desktop/desktop.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/build.go b/build/build.go index 51b035f6dcc2..d92a921170bc 100644 --- a/build/build.go +++ b/build/build.go @@ -278,9 +278,9 @@ func warnOnNoOutput(ctx context.Context, nodes []builder.Node, opts map[string]O var warnNoOutputBuf bytes.Buffer warnNoOutputBuf.WriteString("No output specified ") if len(noOutputTargets) == 1 && noOutputTargets[0] == "default" { - warnNoOutputBuf.WriteString(fmt.Sprintf("with %s driver", noMobyDriver.Factory().Name())) + fmt.Fprintf(&warnNoOutputBuf, "with %s driver", noMobyDriver.Factory().Name()) } else { - warnNoOutputBuf.WriteString(fmt.Sprintf("for %s target(s) with %s driver", strings.Join(noOutputTargets, ", "), noMobyDriver.Factory().Name())) + fmt.Fprintf(&warnNoOutputBuf, "for %s target(s) with %s driver", strings.Join(noOutputTargets, ", "), noMobyDriver.Factory().Name()) } logrus.Warnf("%s. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load", warnNoOutputBuf.String()) } diff --git a/commands/create.go b/commands/create.go index 025a3750ff25..6a275ac3b635 100644 --- a/commands/create.go +++ b/commands/create.go @@ -91,7 +91,7 @@ func createCmd(dockerCli command.Cli) *cobra.Command { if len(drivers.String()) > 0 { drivers.WriteString(", ") } - drivers.WriteString(fmt.Sprintf(`"%s"`, d.Name())) + fmt.Fprintf(&drivers, `"%s"`, d.Name()) } cmd := &cobra.Command{ diff --git a/util/desktop/desktop.go b/util/desktop/desktop.go index 8f01ba4b73d2..7bc91386971f 100644 --- a/util/desktop/desktop.go +++ b/util/desktop/desktop.go @@ -41,7 +41,7 @@ func BuildDetailsOutput(refs map[string]string, term bool) string { multiTargets := len(refs) > 1 for target, ref := range refs { if multiTargets { - out.WriteString(fmt.Sprintf("\n %s: ", target)) + fmt.Fprintf(&out, "\n %s: ", target) } if term { url := BuildURL(ref) From 9f1affa9e8039cf4eaf2889237b30ae20c3a20eb Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 2 Apr 2026 22:44:48 +0200 Subject: [PATCH 2/4] fix ST1016: methods on the same type should have the same receiver name Signed-off-by: Sebastiaan van Stijn --- util/buildflags/attests_cty.go | 42 +++++++++++++++++----------------- util/buildflags/cache_cty.go | 18 +++++++-------- util/buildflags/secrets_cty.go | 20 ++++++++-------- util/buildflags/ssh_cty.go | 20 ++++++++-------- 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/util/buildflags/attests_cty.go b/util/buildflags/attests_cty.go index 2b60b167f870..f26e17564d2d 100644 --- a/util/buildflags/attests_cty.go +++ b/util/buildflags/attests_cty.go @@ -12,46 +12,46 @@ var attestType = sync.OnceValue(func() cty.Type { return cty.Map(cty.String) }) -func (e *Attests) FromCtyValue(in cty.Value, p cty.Path) error { +func (a *Attests) FromCtyValue(in cty.Value, p cty.Path) error { got := in.Type() if got.IsTupleType() || got.IsListType() { - return e.fromCtyValue(in, p) + return a.fromCtyValue(in, p) } want := cty.List(attestType()) return p.NewErrorf("%s", convert.MismatchMessage(got, want)) } -func (e *Attests) fromCtyValue(in cty.Value, p cty.Path) (retErr error) { - *e = make([]*Attest, 0, in.LengthInt()) +func (a *Attests) fromCtyValue(in cty.Value, p cty.Path) (retErr error) { + *a = make([]*Attest, 0, in.LengthInt()) yield := func(value cty.Value) bool { entry := &Attest{} if retErr = entry.FromCtyValue(value, p); retErr != nil { return false } - *e = append(*e, entry) + *a = append(*a, entry) return true } eachElement(in)(yield) return retErr } -func (e Attests) ToCtyValue() cty.Value { - if len(e) == 0 { +func (a Attests) ToCtyValue() cty.Value { + if len(a) == 0 { return cty.ListValEmpty(attestType()) } - vals := make([]cty.Value, len(e)) - for i, entry := range e { + vals := make([]cty.Value, len(a)) + for i, entry := range a { vals[i] = entry.ToCtyValue() } return cty.ListVal(vals) } -func (e *Attest) FromCtyValue(in cty.Value, p cty.Path) error { +func (a *Attest) FromCtyValue(in cty.Value, p cty.Path) error { if in.Type() == cty.String { - if err := e.UnmarshalText([]byte(in.AsString())); err != nil { + if err := a.UnmarshalText([]byte(in.AsString())); err != nil { return p.NewError(err) } return nil @@ -62,7 +62,7 @@ func (e *Attest) FromCtyValue(in cty.Value, p cty.Path) error { return err } - e.Attrs = map[string]string{} + a.Attrs = map[string]string{} for it := conv.ElementIterator(); it.Next(); { k, v := it.Element() if !v.IsKnown() { @@ -71,31 +71,31 @@ func (e *Attest) FromCtyValue(in cty.Value, p cty.Path) error { switch key := k.AsString(); key { case "type": - e.Type = v.AsString() + a.Type = v.AsString() case "disabled": b, err := strconv.ParseBool(v.AsString()) if err != nil { return err } - e.Disabled = b + a.Disabled = b default: - e.Attrs[key] = v.AsString() + a.Attrs[key] = v.AsString() } } return nil } -func (e *Attest) ToCtyValue() cty.Value { - if e == nil { +func (a *Attest) ToCtyValue() cty.Value { + if a == nil { return cty.NullVal(cty.Map(cty.String)) } - vals := make(map[string]cty.Value, len(e.Attrs)+2) - for k, v := range e.Attrs { + vals := make(map[string]cty.Value, len(a.Attrs)+2) + for k, v := range a.Attrs { vals[k] = cty.StringVal(v) } - vals["type"] = cty.StringVal(e.Type) - if e.Disabled { + vals["type"] = cty.StringVal(a.Type) + if a.Disabled { vals["disabled"] = cty.StringVal("true") } return cty.MapVal(vals) diff --git a/util/buildflags/cache_cty.go b/util/buildflags/cache_cty.go index 7186b025ca30..4bbf2fc82ab4 100644 --- a/util/buildflags/cache_cty.go +++ b/util/buildflags/cache_cty.go @@ -59,29 +59,29 @@ func (o CacheOptions) ToCtyValue() cty.Value { return cty.ListVal(vals) } -func (o *CacheOptionsEntry) FromCtyValue(in cty.Value, p cty.Path) error { +func (e *CacheOptionsEntry) FromCtyValue(in cty.Value, p cty.Path) error { conv, err := convert.Convert(in, cty.Map(cty.String)) if err != nil { return err } m := conv.AsValueMap() - if err := getAndDelete(m, "type", &o.Type); err != nil { + if err := getAndDelete(m, "type", &e.Type); err != nil { return err } - o.Attrs = asMap(m) - return o.validate(in) + e.Attrs = asMap(m) + return e.validate(in) } -func (o *CacheOptionsEntry) ToCtyValue() cty.Value { - if o == nil { +func (e *CacheOptionsEntry) ToCtyValue() cty.Value { + if e == nil { return cty.NullVal(cty.Map(cty.String)) } - vals := make(map[string]cty.Value, len(o.Attrs)+1) - for k, v := range o.Attrs { + vals := make(map[string]cty.Value, len(e.Attrs)+1) + for k, v := range e.Attrs { vals[k] = cty.StringVal(v) } - vals["type"] = cty.StringVal(o.Type) + vals["type"] = cty.StringVal(e.Type) return cty.MapVal(vals) } diff --git a/util/buildflags/secrets_cty.go b/util/buildflags/secrets_cty.go index aaadfc39a8e9..4646f7772253 100644 --- a/util/buildflags/secrets_cty.go +++ b/util/buildflags/secrets_cty.go @@ -55,9 +55,9 @@ func (s Secrets) ToCtyValue() cty.Value { return cty.ListVal(vals) } -func (e *Secret) FromCtyValue(in cty.Value, p cty.Path) error { +func (s *Secret) FromCtyValue(in cty.Value, p cty.Path) error { if in.Type() == cty.String { - if err := e.UnmarshalText([]byte(in.AsString())); err != nil { + if err := s.UnmarshalText([]byte(in.AsString())); err != nil { return p.NewError(err) } return nil @@ -69,25 +69,25 @@ func (e *Secret) FromCtyValue(in cty.Value, p cty.Path) error { } if id := conv.GetAttr("id"); !id.IsNull() && id.IsKnown() { - e.ID = id.AsString() + s.ID = id.AsString() } if src := conv.GetAttr("src"); !src.IsNull() && src.IsKnown() { - e.FilePath = src.AsString() + s.FilePath = src.AsString() } if env := conv.GetAttr("env"); !env.IsNull() && env.IsKnown() { - e.Env = env.AsString() + s.Env = env.AsString() } return nil } -func (e *Secret) ToCtyValue() cty.Value { - if e == nil { +func (s *Secret) ToCtyValue() cty.Value { + if s == nil { return cty.NullVal(secretType()) } return cty.ObjectVal(map[string]cty.Value{ - "id": cty.StringVal(e.ID), - "src": cty.StringVal(e.FilePath), - "env": cty.StringVal(e.Env), + "id": cty.StringVal(s.ID), + "src": cty.StringVal(s.FilePath), + "env": cty.StringVal(s.Env), }) } diff --git a/util/buildflags/ssh_cty.go b/util/buildflags/ssh_cty.go index ef580729881f..610228b4db41 100644 --- a/util/buildflags/ssh_cty.go +++ b/util/buildflags/ssh_cty.go @@ -55,9 +55,9 @@ func (s SSHKeys) ToCtyValue() cty.Value { return cty.ListVal(vals) } -func (e *SSH) FromCtyValue(in cty.Value, p cty.Path) error { +func (s *SSH) FromCtyValue(in cty.Value, p cty.Path) error { if in.Type() == cty.String { - if err := e.UnmarshalText([]byte(in.AsString())); err != nil { + if err := s.UnmarshalText([]byte(in.AsString())); err != nil { return p.NewError(err) } return nil @@ -69,25 +69,25 @@ func (e *SSH) FromCtyValue(in cty.Value, p cty.Path) error { } if id := conv.GetAttr("id"); !id.IsNull() && id.IsKnown() { - e.ID = id.AsString() + s.ID = id.AsString() } if paths := conv.GetAttr("paths"); !paths.IsNull() && paths.IsKnown() { - if err := gocty.FromCtyValue(paths, &e.Paths); err != nil { + if err := gocty.FromCtyValue(paths, &s.Paths); err != nil { return err } } return nil } -func (e *SSH) ToCtyValue() cty.Value { - if e == nil { +func (s *SSH) ToCtyValue() cty.Value { + if s == nil { return cty.NullVal(sshType()) } var ctyPaths cty.Value - if len(e.Paths) > 0 { - paths := make([]cty.Value, len(e.Paths)) - for i, path := range e.Paths { + if len(s.Paths) > 0 { + paths := make([]cty.Value, len(s.Paths)) + for i, path := range s.Paths { paths[i] = cty.StringVal(path) } ctyPaths = cty.ListVal(paths) @@ -96,7 +96,7 @@ func (e *SSH) ToCtyValue() cty.Value { } return cty.ObjectVal(map[string]cty.Value{ - "id": cty.StringVal(e.ID), + "id": cty.StringVal(s.ID), "paths": ctyPaths, }) } From c7ebf86714e61ce8b76d76273c8a1b8a9332e512 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 2 Apr 2026 23:03:38 +0200 Subject: [PATCH 3/4] fix / suppress some gosec linting issues Signed-off-by: Sebastiaan van Stijn --- build/build.go | 2 +- build/opt_test.go | 1 + cmd/buildx/debug.go | 4 ++-- docs/generate.go | 2 +- localstate/migrate.go | 1 + store/store.go | 2 +- util/ghutil/ghutil.go | 2 +- util/gitutil/credentials_test.go | 1 + util/imagetools/auth.go | 2 +- 9 files changed, 10 insertions(+), 7 deletions(-) diff --git a/build/build.go b/build/build.go index d92a921170bc..55dd3857de0b 100644 --- a/build/build.go +++ b/build/build.go @@ -1287,7 +1287,7 @@ func ReadSourcePolicy() (*spb.Policy, error) { return nil, nil } - data, err := os.ReadFile(p) + data, err := os.ReadFile(p) // #nosec G703 -- using user-controlled path by design if err != nil { return nil, errors.Wrap(err, "failed to read policy file") } diff --git a/build/opt_test.go b/build/opt_test.go index 0e4499a98ed6..ada2d1111ede 100644 --- a/build/opt_test.go +++ b/build/opt_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" ) +// #nosec G101 -- ignoring: Potential hardcoded credentials func TestCacheOptions_DerivedVars(t *testing.T) { t.Setenv("ACTIONS_RUNTIME_TOKEN", "sensitive_token") t.Setenv("ACTIONS_CACHE_URL", "https://cache.github.com") diff --git a/cmd/buildx/debug.go b/cmd/buildx/debug.go index 49766c686307..a43df0f038d0 100644 --- a/cmd/buildx/debug.go +++ b/cmd/buildx/debug.go @@ -27,7 +27,7 @@ func setupDebugProfiles(ctx context.Context) (stop func()) { func setupCPUProfile(ctx context.Context) (stop func()) { if cpuProfile := os.Getenv("BUILDX_CPU_PROFILE"); cpuProfile != "" { - f, err := os.Create(cpuProfile) + f, err := os.Create(cpuProfile) // #nosec G703 -- using user-controlled path by design if err != nil { bklog.G(ctx).Warn("could not create cpu profile", logrus.WithError(err)) return nil @@ -53,7 +53,7 @@ func setupHeapProfile(ctx context.Context) (stop func()) { if heapProfile := os.Getenv("BUILDX_MEM_PROFILE"); heapProfile != "" { // Memory profile is only created on stop. return func() { - f, err := os.Create(heapProfile) + f, err := os.Create(heapProfile) // #nosec G703 -- using user-controlled path by design if err != nil { bklog.G(ctx).Warn("could not create memory profile", logrus.WithError(err)) return diff --git a/docs/generate.go b/docs/generate.go index 9d5f7a92c5e5..ac76833521f3 100644 --- a/docs/generate.go +++ b/docs/generate.go @@ -165,7 +165,7 @@ func generateBakeStdlibDocs(filename string) error { } newContent := before + "\n\n" + table.String() + "\n" + currentContent[end:] - return os.WriteFile(filename, []byte(newContent), 0644) + return os.WriteFile(filename, []byte(newContent), 0644) // #nosec G703 -- using parameterized path by design. } type mdTable struct { diff --git a/localstate/migrate.go b/localstate/migrate.go index 1334e1de2c35..7378451cb882 100644 --- a/localstate/migrate.go +++ b/localstate/migrate.go @@ -29,6 +29,7 @@ func (ls *LocalState) MigrateIfNeeded() error { } func (ls *LocalState) migration2() error { + // #nosec G122 -- TODO: consider using os.Root to prevent TOCTOU return filepath.Walk(ls.GroupDir(), func(path string, info os.FileInfo, err error) error { if err != nil { return err diff --git a/store/store.go b/store/store.go index d27fda623da6..e49f3727ff00 100644 --- a/store/store.go +++ b/store/store.go @@ -84,7 +84,7 @@ func (t *Txn) NodeGroupByName(name string) (*NodeGroup, error) { if err != nil { return nil, err } - dt, err := os.ReadFile(filepath.Join(t.s.cfg.Dir(), instanceDir, name)) + dt, err := os.ReadFile(filepath.Join(t.s.cfg.Dir(), instanceDir, name)) // #nosec G703 -- name is validated and using user-controlled path by design if err != nil { return nil, err } diff --git a/util/ghutil/ghutil.go b/util/ghutil/ghutil.go index e1ca13bfb1cf..0c96c8b84a08 100644 --- a/util/ghutil/ghutil.go +++ b/util/ghutil/ghutil.go @@ -30,7 +30,7 @@ func GithubActionsContext() ([]byte, error) { // "GITHUB_EVENT_NAME": "push" // "GITHUB_EVENT_PATH": "/home/runner/work/_temp/_github_workflow/event.json" m["github_event_name"] = githubEventName - dt, err := os.ReadFile(githubEventPath) + dt, err := os.ReadFile(githubEventPath) // #nosec G703 -- using parameterized path by design if err != nil { return nil, errors.Wrapf(err, "failed to read GITHUB_EVENT_PATH %q", githubEventPath) } diff --git a/util/gitutil/credentials_test.go b/util/gitutil/credentials_test.go index 7225f8dc1b2b..28482906d68e 100644 --- a/util/gitutil/credentials_test.go +++ b/util/gitutil/credentials_test.go @@ -2,6 +2,7 @@ package gitutil import "testing" +// #nosec G101 -- ignoring: Potential hardcoded credentials func TestStripCredentials(t *testing.T) { cases := []struct { name string diff --git a/util/imagetools/auth.go b/util/imagetools/auth.go index f33c9b2c99c2..6dc03b360b71 100644 --- a/util/imagetools/auth.go +++ b/util/imagetools/auth.go @@ -34,7 +34,7 @@ func RegistryAuthForRef(ref string, auth authprovider.AuthConfigProvider) (strin if err != nil { return "", err } - buf, err := json.Marshal(ac) + buf, err := json.Marshal(ac) // #nosec G117 -- Ignore "JSON key "password" matches secret pattern" if err != nil { return "", err } From 945f9c79cc6ed3b4c6cc3070586d235ca6e63bee Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 2 Apr 2026 23:05:44 +0200 Subject: [PATCH 4/4] golangci-lint: disable QF1008 It's often too opinionated; there's valid reasons to be explicit and not depend on embedding. Signed-off-by: Sebastiaan van Stijn --- .golangci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 7a6204468a88..3e62826bbdf6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -74,6 +74,12 @@ linters: alias: "ocispecs" - pkg: "github.com/opencontainers/go-digest" alias: "digest" + staticcheck: + # Enable all options, with some exceptions. + # For defaults, see https://golangci-lint.run/usage/linters/#staticcheck + checks: + - all + - -QF1008 # Omit embedded fields from selector expression; https://staticcheck.dev/docs/checks/#QF1008 testifylint: disable: - empty