February 10, 2022·5 min read·engineeringgosecurityvalidationmodules

Go 1.17.7 repairs assumptions about valid inputs

February's Go security release fixes coordinate validation, rational-number parsing and module version resolution. Each defect concerns a value that looked acceptable before the next operation used it.

A branch named like a release is still a branch. Go's module resolver did not always preserve that distinction, which could undermine repositories that allow more people to create branches than tags. The February security release repairs that mistake alongside two library defects involving numeric inputs. Their common concern is the meaning of validation at a boundary where the next operation assumes more than the previous check established.

The release history for Go 1.17.7 dates the release to 10 February 2022. It lists security corrections in the go command, crypto/elliptic and math/big, alongside ordinary bug fixes. The release announcement supplies the security descriptions and identifies Go 1.16.14 as the corresponding maintenance release for the older branch.

I like Go's explicit treatment of failure because it makes operational decisions visible in ordinary code. These fixes concern cases where the underlying contract was already weaker than a caller could reasonably infer. A successful check is useful only when it establishes the property that the following operation needs.

A release-looking name did not establish a release

The go command defect is CVE-2022-23773. The announcement describes branches named v1.0.0 or subdir/v2.0.0-dev becoming module versions. Repository access controls can distinguish branch creation from tag creation. Interpreting both kinds of reference as releases can therefore give branch-writing authority consequences that the repository policy intended to reserve for tag writers.

The module resolution patch explains the implementation error. A shortcut accepted the requested version when it resolved successfully and already had canonical version syntax. That shortcut skipped the distinction between resolving a name and verifying a release tag. The correction removes the special case and uses the more general tag-selection logic.

The patch's tests make the changed behavior concrete. A version-shaped branch can now produce an error explaining that the requested name is not a tag, with the resolved version included in the diagnostic. This matters because silently substituting another version would introduce a different ambiguity. A request for a particular release should not conceal the fact that the repository lacks the corresponding release tag.

The security property depends on repository policy. This is not a claim that all branches are untrusted or that a tag inherently authenticates its author. The issue is whether the resolver preserves a distinction on which the repository's authorization rules rely. A permission boundary is ineffective when a downstream tool merges the categories it separates.

That gives this patch practical significance for build infrastructure. Reviewing who can publish releases requires understanding which repository objects the dependency tool treats as releases. Restricting tag creation is only one part of that arrangement. The consumer must require the reference kind that the restriction protects.

An arbitrary integer is not a valid coordinate

CVE-2022-23806 concerns crypto/elliptic's IsOnCurve operation. The primary issue analysis describes coordinates represented by big.Int even though field elements must lie between zero and P minus one. Negative integers and values at least P are invalid representations of those elements. Some implementations nevertheless returned true for such values.

Subsequent curve operations did not handle those accepted values consistently. Guido Vranken's original report involved coordinates that passed IsOnCurve and then caused ScalarMult to panic. The analysis also describes invalid curve operations, which can have cryptographic consequences. Go 1.17.7 makes IsOnCurve reject negative and overflowing field elements.

The issue is instructive because the representation admits more values than the mathematical object. A general integer type cannot by itself establish that a coordinate is in the required field. The validation function has to enforce that restriction before an operation relies on it. Reducing a value during one calculation does not establish that every later operation interprets the original representation the same way.

The announcement says Unmarshal never returns the invalid values involved here. That narrows the immediate exposure and prevents an inaccurate conclusion that every ordinary decoded point follows the vulnerable path. Callers constructing or manipulating coordinates directly deserve particular attention. The distinction follows the data path through the API instead of treating every use of the package as equivalent.

My preference for small interfaces is relevant here. An interface that accepts a representation broader than its valid domain transfers obligations to its callers. When those obligations are necessary, the validation operation needs a precise contract that agrees with the operations it protects.

The exponent check overflowed before it checked the limit

CVE-2022-23772 fixes unbounded memory consumption in Rat.SetString. The issue report also identifies UnmarshalText and Scan as reachable entry points. Code that converts text into a rational number can encounter the defect through another API, even when it never calls SetString by name.

The math/big patch adds a check after negating a negative exponent component. Negating the minimum signed 64-bit integer overflows and leaves it negative. The existing comparison against a positive upper bound consequently fails to reject it. The new condition rejects a value that remains negative after the attempted sign conversion.

That is a specific arithmetic failure in a resource guard. The guard already attempted to reject excessively large exponents. Its preparation step assumed that taking the magnitude would produce a nonnegative value. The representation's asymmetric range invalidated that assumption before the upper-bound comparison ran.

This distinction matters for application limits. A short textual representation can describe a very large exponent, so limiting input length alone does not prove that conversion has a reasonable allocation cost. The repaired parser must reject the arithmetic corner case. Application-level limits still express the amount of work appropriate for a particular service, which is a separate policy.

The library fixes and the tool fix affect different work

The release contains changes for programs that process numeric values and for the tool that resolves dependencies. Library corrections concern the behavior of code built with the repaired library. Updating the go command changes dependency resolution. An inventory limited to deployed services can miss build workers, while an inventory limited to compiler installations can miss existing application artifacts.

I regard this as a useful example of why a maintenance release deserves a technical reading. The version number alone does not explain which assumptions changed. Here the relevant distinctions are the accepted coordinate range, arithmetic behavior during parsing, and the repository reference used to establish a module version. Each provides a concrete way to identify affected code or infrastructure without claiming that every Go program has the same exposure.