fix: a build without the tags refuses, and every analysis job passes them - #65
Merged
Conversation
…them Two halves of one gap, both found by an outside review on 2026-09-05 and confirmed here. A build without the tags now stops at the compiler. The AVIF encoder's AVX2 path reads past the end of a buffer and takes the process down on some picture sizes - measured at 640x256, in two runs out of three - and the tag that turns it off has been in .github/build-tags since the encoder arrived. Every workflow step passes it. None of the three ways README.md offered for building it yourself did, so go install, a distribution package and a build from a checkout all got that path. Both binaries reach it: internal/format/all registers AVIF unconditionally. Failing at build time is the honest place. The alternatives were weighed: registering AVIF as unavailable keeps go install working but makes "tfg formats" answer differently depending on how the binary was made, and inverting the tag is a larger change to CI and the byte contract for no more safety. Owner's call. Three CI jobs analysed a build we do not ship. govulncheck, staticcheck and golangci-lint are each fetched with "go run" and pointed at ./..., and that loads and type checks our packages exactly as the compiler does - so the reachability analysis ran through files no released binary contains. The guard could not see them because it recognised only go build, go test and go vet, and said in its own comment that somebody else's tool was not ours to tag. Two more places came out with them: release.yml read the version with "go run ./cmd/tfg version" and no tags, and cmd/tfg links AVIF. All three tools were run with the flags before this was written: -tags for govulncheck and staticcheck, --build-tags for golangci-lint, all clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both matched the exact text of a workflow line, so adding the build tags in front of a package pattern read as a job that had disappeared. They ask for the package and the verb now, which is what the job has to do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two built cmd/tfg without the build tags, which stopped compiling when the missing tag became a refusal - and one of them reported that as a SKIP rather than as a failure, which is the silent shape this project has paid for before. The third matched the literal text of a workflow line and read an added flag as a job that had disappeared. Measured while fixing them: the tags do NOT change the dependency set of cmd/tfg - go list -deps returns the same packages either way, zero lines differing - so the guards that ask what the binary links were answering correctly. What the tags change is which files are compiled, which is why the analysis jobs needed them and these builds do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
donislawdev
force-pushed
the
security/build-tags
branch
from
September 6, 2026 13:27
3464a98 to
3154161
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two halves of one gap. Findings
S2andS5of the outside security review, both confirmed here before anything was written.A build without the tags now stops at the compiler
internal/format/avif/avif.gohas said since the encoder arrived that its AVX2 path reads past the end of a buffer and takes the process down on some picture sizes - measured at 640x256, in two runs out of three. The tag that turns it off lives in.github/build-tags, every workflow step passes it, and two guards keep those steps honest.None of that reached somebody building the program themselves.
README.mdoffered three ways and not one carried the tag, sogo install ...@latest, a distribution packager and a contributor running from a checkout all got that path. Both binaries reach it -internal/format/allregisters AVIF unconditionally andgo list -depssayscmd/tfglinks it.Failing at build time is the honest place: the alternative is a binary that works until it meets the wrong picture size. The other shapes were weighed and turned down - registering AVIF as unavailable keeps
go installworking but makestfg formatsanswer differently depending on how the binary was made, and inverting the tag is a larger change to CI and the byte contract for no more safety. Owner's call.Three analysis jobs read a build we do not ship
govulncheck,staticcheckandgolangci-lintare each fetched withgo runand pointed at./..., which loads and type checks our packages exactly as the compiler does. The guard could not see them because it recognised onlygo build,go testandgo vet, and said in its own comment that somebody else's tool was not ours to tag.Two more came out with them:
release.ymlread the version withgo run ./cmd/tfg versionand no tags, andtools/preflight.pyran-race,vet,golangci-lintandgovulncheckwithout them - so the local gate and CI were measuring different builds. All three tools were run with the flags before this was written (-tagsfor two,--build-tagsfor the linter), all clean.What the refusal then found
Turning the missing tag into a compile error made four more callers show themselves, and one of them was a guard that skipped instead of failing when its build broke - the silent shape this project has paid for before. Two others matched the literal text of a workflow line and read an added flag as a job that had disappeared.
Measured while fixing them: the tags do not change the dependency set of
cmd/tfg-go list -depsreturns the same packages either way, zero lines differing. What they change is which files are compiled, which is why the analysis jobs needed them and thego listguards did not.Guards
TestABuildWithoutTheBuildTagsRefusesAndSaysWhyasks the compiler rather than the source.TestTheInstallInstructionsCarryTheBuildTagskeeps the one copy of the tag that cannot read the file honest, since it is typed before the repository exists.compilesOurCodenow recognisesgo runpointed at our packages. Three new mutations, all caught, plus two existing ones repaired rather than counted.🤖 Generated with Claude Code