Help us shape the future of Go! Take the 2026 Go Developer Survey

zeroguard

command
v1.8.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Command zeroguard finds gopherstack Update/Put/Modify handlers that cannot distinguish "the caller omitted this field" from "the caller sent the zero value" and silently resolve the ambiguity the wrong way -- gopherstack-6flj's newest bug class, first confirmed in apigatewayv2.UpdateAuthorizer and fixed in commit 406c1dcc3.

TWO SIGNALS, read straight from the pinned aws-sdk-go-v2 source with go/ast (the SDK module resolution is cmd/enumcheck's own approach, modresolve.go, copied verbatim):

  • A: a gopherstack <Op>Input struct field declared as a plain predeclared scalar (int32, int64, int, bool, string, float32, float64) where the real pinned SDK's <Op>Input declares the SAME field (matched case-insensitively, since gopherstack and the SDK sometimes differ only in an abbreviation's casing -- AuthorizerResultTTLInSeconds vs. AuthorizerResultTtlInSeconds) as a POINTER to that same scalar type. Read from api_op_<Op>.go's own struct declaration, sdkfields.go -- not a name guess, since every aws-sdk-go-v2 service is smithy-go codegen and this shape is uniform across all wire protocols, unlike enum/wire-key ground truth which varies by protocol.
  • B: an if-statement in the handler gating a use of that field on it being non-zero (!= 0, != "") or, for a bool field, directly truthy -- the exact shape the pre-fix apigatewayv2.UpdateAuthorizer guards had.

CONFIDENT requires BOTH: the real member is a pointer, gopherstack's is not, AND a zero-guard gates its application. Signal A alone is common and often harmless (many fields are genuinely required, or a required identifier is always present from routing and never guarded at all) -- reported as NEEDS REVIEW.

SCOPE: only files directly in services/<dir> (no recursion into subpackages), only Update/Put/Modify-named operations (a Create op takes a fresh resource with no prior state an omission could accidentally erase), only a handler's OWN Input-struct fields (a nested struct field inside, e.g. Route53AutoNaming's DnsConfig.DnsRecords, is a different shape -- a pointer-to-struct presence check whose omission needs to CASCADE a delete, not a scalar zero-guard -- and is out of this tool's signal entirely; see the package's final report for why).

Usage:

go run ./cmd/zeroguard                   # report to stdout
go run ./cmd/zeroguard -json out.json     # also write full finding list as JSON

Exit codes: 0 no confident findings (needs-review hits may still print), 1 a run error, 2 at least one confident finding.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL