Go 1.15.5 repairs cgo build-time trust boundaries
The November security release closes two paths from package inputs to build-time execution. It also corrects a recursive-division shift in math/big.
Building a package and running its program grant different kinds of authority. Go 1.15.5 repairs two cgo paths that let malicious package inputs cross that boundary during a build. One involves compiler flags in a cgo directive. The other involves an object-file symbol name inserted into generated Go source. Both exploit translation between representations that carry more authority than the original data should receive.
The release entry also identifies a security fix in math/big. That repair changes a shift used by recursive division. It addresses a separate runtime failure, where crafted large inputs can provoke a panic. Keeping the build-time and runtime problems separate helps explain what each part of the update protects.
I value Go's distinction between fetching or building code and choosing to execute a program. Native build tools complicate that distinction because their flags can invoke behavior far beyond compiling a harmless declaration. The cgo checks need to preserve the boundary across those tools.
A symbol becomes generated source
The object-symbol repair describes a hand-edited object file containing a symbol name with newlines or other normally invalid characters. Cgo generated Go files containing symbol names without quoting them. A name that should have remained data could consequently introduce additional Go source.
The particularly consequential injected source was a //go:cgo_ldflag directive. That directive could cause the C linker to execute arbitrary code while building the package. The problem was not simply that the package could contain malicious runtime behavior. The build process encountered authority that the user had not granted by deciding to build the package.
The patch repairs two boundaries. Cgo rejects symbols containing nonprintable characters, spaces, or text resembling a Go comment. The Go command also checks the linker-flag directives in generated code against its existing restrictions. These checks protect both entry into generated source and the later interpretation of a directive with build-time effects.
The second check matters even though the first rejects the reported symbol form. Generated files are still inputs to another stage. Validating the authority-bearing directive at that stage prevents the consumer from assuming that every producer has already established all of its requirements.
This is CVE-2020-28366. The commit explicitly distinguishes running imported code from executing code during its build. That distinction is part of the threat model stated by the repair itself. It explains why ordinary knowledge that source code can be malicious does not dismiss a build-time injection defect.
Flag validation must model argument grammar
The compiler-flag correction addresses CVE-2020-28367. It narrows accepted -D and -U arguments to ASCII C identifiers while preserving trailing digits. The validation must recognize actual macro names instead of accepting almost any remaining text after an initial letter or underscore.
The distinction between direct flags and preprocessor-forwarding flags also matters. In -Wp, arguments, commas separate material passed onward to the preprocessor. A comma inside a purported macro value can therefore introduce another argument. The revised rule excludes commas from those values.
The tests show the intended distinction with compact examples.
-Dfoo=bar
-Ufoo1
-Wp,-Dfoo1
-Wp,-Ufoo1
These accepted forms preserve ordinary macro definitions and undefinitions. Separate rejected test cases include forwarding forms that try to introduce an additional macro argument involving @. The validator cannot decide safety by looking only at the first option prefix. It needs to account for the grammar that the next tool will apply to the rest of the string.
This illustrates why a flag allowlist requires more than a collection of recognizable spellings. The consumer may split one apparent argument into several internal arguments. Validation has to follow that interpretation far enough to exclude the behavior the boundary forbids.
The correction also permits names ending in digits. A security restriction that accidentally rejects valid identifiers would impose a compatibility cost unrelated to the defect. The patch treats narrowing unsafe syntax and retaining valid macro names as parts of the same grammar repair.
Recursive division gets a smaller correction
The math/big patch changes a local shift from B to B - 1. Its surrounding comment already described choosing B - 1. The recursive step slices its dividend and divisor using that shift, so the wrong boundary affects the lower portion of the computation.
The release identifies this as CVE-2020-28362. Its security announcement explains that crafted large arguments can make several integer and rational operations panic. It gives divisor or modulus thresholds above 3168 bits on 32-bit architectures or 6336 bits on 64-bit architectures. Certificate verification can reach the defect before a chain has been accepted as trusted.
That last condition prevents an easy but incorrect dismissal. Rejecting an untrusted certificate is not sufficient if the computation needed to reject it can panic first. The arithmetic library participates in security-sensitive operations even when application code does not explicitly perform large-number division.
The code change is much smaller than the cgo validation changes, but patch size does not establish exposure. Recursive arithmetic shares an implementation across several higher-level operations. Correcting one boundary inside that implementation can repair multiple callers without changes to their APIs.
The arithmetic commit credits the Go Ethereum team and OSS-Fuzz for the report, with additional help developing and validating the correction. Those reports concern the shared numerical implementation, which explains why the release announcement enumerates consequences beyond direct callers of division.
Different artifacts need different updates
The cgo defects concern the toolchain performing a build. Updating a deployed binary does not repair a separate machine that continues to build untrusted packages using the vulnerable tools. The division defect concerns arithmetic in the compiled program, so rebuilding with the corrected implementation matters for the running artifact.
I regard this release as a useful reminder to name the affected operation precisely. A build input crossing into linker authority needs validation at translation boundaries. A large-number operation needs a correct recursive split before callers can rely on its error behavior. Go 1.15.5 supplies those separate corrections within the existing release line.