Last Week on My Mac: How an RSR went badly wrong

Last week broke new ground in being the first in which Apple released two Rapid Security Responses (RSR) within two days. On 10 July, it released RSR 13.4.1 (a), but removed it a few hours later, then replaced it by RSR 13.4.1 (c) on 12 July. As far as we’re aware, both patched the same vulnerability in WebKit, but the first also broke popular web services including Facebook. The causes of this fiasco should have been anticipated, and were entirely preventable.

The underlying problem wasn’t for once the result of the patched code in the RSR, but Apple’s version numbering, something I and others had highlighted when Apple released its first RSR on 1 May. As I explained then, Apple changed its version numbering system without any explanation or warning, and in a way that broke its parsing by many third parties.

Previously, Apple had numbered macOS versions using the scheme [major].[minor].[patch], as in 13.4.1 and that for bundle versions. Rather than count an RSR as a patch, or add a fourth digit to take the version number to 13.4.1.1, it decided to append a letter, and even worse to put that in parentheses. The first of last week’s two RSRs thus changed the macOS version number to 13.4.1 (a).

With its very first RSR in May, Apple also incremented Safari’s build number, taking it from 18615.1.26.11.23 to 18615.1.26.110.1, but its version number remained at 16.4. The fatal mistake last week was that Safari’s version was also changed this time, from 16.5.1 to 16.5.2 (a). Changing the version number of a browser has more widespread impact, as that’s included in its User Agent, information that’s checked by many websites that the browser connects to. Without prior warning, Safari’s User Agent went from 16.5.1 to 16.5.2 (a), and some servers simply couldn’t accept that, so refused to continue their connection with all Macs that had installed RSR 13.4.1 (a).

This in turn results from the User Agent being sent as a text string, rather than anything structured to cope with such changes in the format of version numbers. Parsing text strings robustly to extract version numbers whose structure can change requires surprising care, and clearly wasn’t of concern to some major services. It’s as much a reflection on poor programming practice on the part of those analysing the User Agent, as on Apple’s lack of forethought of the consequences of changing Safari’s User Agent in that way.

This also raises the question of why some web services should block connections when they don’t fully recognise the User Agent. From its inception, the World Wide Web was intended to be largely independent of platform and software. Its protocols are designed to be implemented on all systems that can connect to the internet. Yet when servers encountered a browser version they didn’t recognise, their response wasn’t to fall back to a default behaviour, but to deny that connection altogether. Instead of being a common language, the internet has increasingly deviated from its original objectives to the detriment of its users.

Apple has also failed to recognise that version numbers are a public means of communication with developers, users, administrators and servers, not a private playground like build numbers. I’ve been unable to find any documentation from Apple explaining its numbering system before it started releasing RSRs, and it certainly hasn’t defined its system since. Why is the RSR letter enclosed in superfluous parentheses? Does Apple intend using these letters without parentheses, such as 13.4.1 a, for another purpose? Why did the second RSR jump to (c) when the previous release was (a)? Perhaps most of all, why with its May RSR did Apple change Safari’s build but not version number, and then do the opposite on 10 July?

The implication is that Apple has not only failed to communicate its version numbering system to the public, but hasn’t even defined it for its own engineers.