Go 1.22.4 corrects ZIP interpretation and mapped address classification
The June security update fixes disagreement over ZIP directory records and incorrect predicates for IPv4-mapped IPv6 addresses. Both matter when parsed data informs a trust decision.
Two programs can read identical bytes and disagree about which files an archive contains. A network filter can also classify two representations of an address differently. Go 1.22.4, released on June 4, fixes security defects in both situations. The common concern is interpretation before an application makes a decision about external data.
The ZIP defect involves a malformed end-of-directory record and a search that continued past it. The address defect involves predicates that failed to account for IPv4-mapped IPv6 addresses. Neither requires memory corruption to matter. A program can remain within the language's memory-safety rules while acting on a mistaken understanding of its input.
I value Go's readable control flow because it makes policy easier to find in application code. These fixes are a reminder that a clear conditional still depends on the library operation supplying the right meaning. The predicate and parser are part of that policy's implementation.
A ZIP reader must choose a directory record
The ZIP report, issue 66869, describes a constructed archive with an outer end-of-central-directory record whose comment length is inconsistent with the available comment bytes. The old reader skipped that candidate and continued searching for another record. An earlier record inside the supplied content could then determine the files that Go extracted.
Other ZIP implementations did not necessarily make that same choice. The report demonstrates that a Go reader and other readers could expose different archive contents from one input file. The maintainers assigned CVE-2024-24789 through the backport request and treated the mismatch as a security issue.
This is relevant when one program inspects an archive and another consumes it. A decision that the first reader makes concerns the entries that reader sees. If a second reader selects a different directory, the decision does not describe the second reader's output. This is an application consequence of parser disagreement, rather than a claim that every archive-processing application implements such a multi-stage workflow.
The malformed comment matters because it influences the record search. The vulnerable behavior attempted to recover by looking for a different candidate. Recovery can be useful for damaged input, but here it changed which structural record the parser trusted. An archive with multiple plausible records makes that choice observable.
The patch stops recovery past a truncated comment
The released ZIP reader source makes the relevant change concrete. Its signature search scans backward for an end-of-central-directory marker. After finding a candidate, it reads the declared comment length and checks whether the comment would extend beyond the available bytes.
In the fixed search, a truncated comment returns failure. The reader does not continue scanning earlier positions within that block for a substitute record. This is the important behavioral boundary. The parser no longer treats this particular malformed candidate as permission to select an earlier archive structure.
A comment in the implementation notes that some parsers, including Info-ZIP, ignore the truncated comment instead of treating it as a hard error. Therefore the repair should not be described as making every ZIP parser accept or reject exactly the same files. Its purpose is to prevent Go's specific fallback from exposing a different earlier archive through this malformed-record construction.
The directory-reading code also checks comment length when reading the selected record. There is a difference between validating the chosen record and deciding which record is chosen. Security depends on both. A reader can validate its eventual selection while still having made an unsafe recovery decision during the search.
No archive example needs to execute for this disagreement to matter. The issue is the inventory produced by reading directory metadata. The report contains a malicious sample, but the mechanism can be understood from the record-selection logic without opening that sample.
Mapped addresses need the embedded IPv4 classification
The second advisory, CVE-2024-24790, concerns net/netip methods such as IsPrivate and IsLoopback. For IPv4-mapped IPv6 addresses, affected methods returned false where the equivalent traditional IPv4 form returned true.
The distinction is visible in the release-tag implementation. This package recognizes an IPv4-in-IPv6 representation and provides Unmap to obtain the IPv4 form. The corrected IsPrivate first checks for that representation and unmaps it before applying its IPv4 classification.
The beginning of that method now includes this conversion:
if ip.Is4In6() {
ip = ip.Unmap()
}
Afterward, the method checks the IPv4 private ranges if the address is IPv4. Its source names the RFC 1918 ranges. Ordinary IPv6 classification uses the unique-local range specified by RFC 4193. Unmapping ensures that a mapped IPv4 address reaches the appropriate IPv4 decision.
This is a semantic conversion, not a textual cleanup. Simply displaying an address differently would not repair the predicate. The classification needs to operate on the address family represented by the embedded value.
A predicate supplies a fact within a larger policy
An application that rejects private or loopback destinations may use these methods as part of its decision. Returning false for a mapped representation can make that decision differ from the decision for the equivalent IPv4 representation. The advisory establishes the predicate defect. Whether it becomes an authorization failure depends on the application's rules and how it uses the result.
IsPrivate also has a specific documented scope in the source. It recognizes the listed private or unique-local ranges. That is not equivalent to a complete definition of a permissible destination for every application. The fix makes the method's classification consistent for the affected representations, while the caller still chooses the policy that classification informs.
I prefer predicates with this narrow, inspectable meaning. A destination policy can state which address properties it uses, and the implementation can classify mapped addresses according to those properties. The useful guarantee here is that a different representation does not bypass the intended IPv4 classification.
The ZIP and address repairs act at different stages of interpretation. ZIP record selection determines which entries the reader describes. Address normalization determines which family-specific classification applies. Go 1.22.4 corrects those operations so callers receive the archive structure and address properties that these library paths are intended to report.