| > Affected developers will unwittingly distribute the malicious trojan to their users in the form of the compromised Xcode projects, and methods to verify the distributed file (such as checking hashes) would not help as the developers would be unaware that they are distributing malicious files. To understand why this happens, it's important to know how massive a typical .pbxproj file looks: https://opensource.apple.com/source/CommonCrypto/CommonCrypt... Ostensibly it's human-readable, but because it's generated by Xcode and filled with inscrutable UUIDs, people treat it like a binary file, and they're trained to do so: https://stackoverflow.com/questions/2004135/how-to-merge-con... Even the React Native team apparently allowed the file to be treated as non-diffable for some time: https://github.com/facebook/react-native/pull/11047 And note the large number of commits on all types of projects that essentially say "whoops forgot to update pbxproj" - there are likely far more. https://github.com/search?q=update+pbxproj&type=Commits So why does this matter? Because the brilliance of this attack is how it "jumps the blood-brain barrier" between a developer's machine and their canonical codebase. Usually, code review and auditing of what goes into a commit prevents this kind of attack from leaping to VCS. But Apple makes the pbxproj so inscrutable, and does such a good job at hiding all its complexity behind (usually well-designed) wizards and dropdown menus, that people take it for granted. If code shows up there, people believe Apple intended that to be the case even if, say, your last commit was a small change in Interface Builder (or whatever they call it nowadays). Your code reviewer might just skip the file entirely, because they've been trained to expect the same. And that's scary. At the end of the day, this is just another way of exploiting the lack of a mature and centralized CI ecosystem in the modern package distribution world. There's no organization running a security-minded linter on pbxproj files as a general rule. But, then again, there doesn't need to be a linter on package.json or project.clj or Makefiles because there was never a history of hiding complexity - if that file changes, you'd better darn well know what you're doing. What we have here is a perfect storm of move-fast-break-things package management, a file designed to slip through code reviews, and a pretty creatively designed malware payload. EDIT: Perhaps another way to look at it is that having one file responsible for both compilation logic and non-compilation-related IDE-specific file status can be problematic. It's like your Makefile also needs to be your .gitignore-but-only-top-level-is-allowed-and-all-files-need-to-be-whitelisted. Of course, this is very much an Apple thing to do. |