zeroguard

command
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 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