According to Xcode: 'The identity of a repository hosted on "github.com" has changed'

Hello,

I am working on a project which uses swift packages hosted on GitHub from Xcode.

Recently when resolving packages over SSH I am running into this issue:
screenshot_2021-11-17_at_15.48.13

It took me a while to figure out what this 7B99811E4C91A50D5A2E2E80133F24CA even is. Typically, RSA fingerprints are given as base64 encoded SHA256 hashes. That thing looks like hexadecimal and does not have enough bits. I suspect it is an MD5 digest.

According to GitHub's SSH key fingerprints - GitHub Docs Github's RSA key fingerprint is:

SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8

I have since figured out that the MD5 digest is supposed to be:

1627aca576282d36631b564debdfa648 (or MD5:16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48 as it would more typically be written by ssh tools).

As we can see, this does not match with what Xcode tells me, hence I am reluctant to click "Trust".

My ~/.ssh/known_hosts file has a public key associated with github.com which matches the published SHA265 fingerprint.

My ~/Library/Preferences/com.apple.dt.Xcode.plist (which Xcode apparently uses for storing known hosts?) contains github.com mapped to 1627aca576282d36631b564debdfa648. This also looks correct (except for using MD5 in 2021, but that is another issue).

Interestingly, when I try to resolve these packages using the command xcodebuild -resolvePackageDependencies things work without changing any known hosts. The same is true when I try to clone the repositories just using git. doing ssh-keyscan github.com also returns the RSA public key, which SHA264 hashes and MD5 hashes to the expected values.

What I would ultimately like to achieve is resolving these packages from Xcode without trusting 7B99811E4C91A50D5A2E2E80133F24CA. Or at least confirming that 7B99811E4C91A50D5A2E2E80133F24CA is trustworthy before trusting it.

Any help would be appreciated, but I have two questions in particular:

  1. A possibility is that when resolving packages from the Xcode GUI, I am really not talking to github.com, but someone/thing else. How can I debug this. Is there some verbose mode where I can get more information? Something like what GIT_SSH_COMMAND="ssh -vvv" git clone example provides on the command line.

  2. Another possibility is that Xcode has somehow confused itself and is asking me to trust a wrongly constructed key fingerprint. Could this be the case?

Any other possible explanations?

4 Likes

One thing that comes into play is that resolving packages in Xcode uses Xcode's built-in SCM support and account system whereas xcodebuild uses SwiftPM's (which is essentially shelling out to git directly) because that has proven to work more reliable in CI contexts which is the typical use case of xcodebuild. You can switch to Xcode's built-in SCM support by passing -scmProvider xcode.

@NeoNacho thanks for the tip. I dug a bit further.

It seems that different SSH implementations are indeed used between the system SCM tools and the xCode ones.

This causes different SSH hostkey algorithms to be chosen. xCode must have previously also used RSA, but recently changed to use ECDSA (can also be due to recent changes by GitHub. It seems their support for ECDSA is recent). The system SSH still ends up negotiating RSA for the hostkey algorithm.

In any case, if I obtain GitHub's ECDSA hostkey by doing ssh-keyscan -t ecdsa github.com and then MD5 hash it (after checking the SHA265 hash matches the published one, and performing necessary base64 to/from hex conversions), I indeed get: 7B99811E4C91A50D5A2E2E80133F24CA.

If I wanted to suggest that xCode started displaying SSH hostkey fingerprints using SHA265 instead of (or maybe in addition to) MD5, is there an official place for doing that? Or maybe that can already be configured somewhere?

You can file an Xcode feature request at https://feedbackassistant.com

Confirm thusly:

$ ssh-keyscan -t ecdsa github.com | cut -w -f 3 | base64 -d | md5
# github.com:22 SSH-2.0-babeld-a73e1397
7b99811e4c91a50d5a2e2e80133f24ca
1 Like

Confirm thusly:

And really one ought to also take the sha256 hash and check that one matches what GitHub has published at: GitHub's SSH key fingerprints - GitHub Docs. You need to cross-reference with a known, trusted fingerprint to actually confirm anything. Bash one-liner left at an exercise to the reader, but consider that technically it is important to take both hashes of the same key, so run ssh-keyscan once and hash the result with each hash algorithm.

I case anybody is curious, I think I have found out why xCode reports the host as changed and not the system git or ssh.

It seems that if no known key exists on the system, both my system ssh and xCode will currently end up using ECDSA for GitHub, now that GitHub as added support for it. i.e. ECDSA is by default prioritized over RSA by newer ssh clients in general it seems.

xCode, for some reason, keeps track of its own known hosts in ~/Library/Preferences/com.apple.dt.Xcode.plist. As opposed to the actual known_hosts file, this file does not store the key type.

When ssh uses the known host file, it will read the entry for the host before connecting to the server. it will then prioritize using the key type of a known key for host verification.

xCode tries to do its own management of known keys. But it seems to just assume that all host keys are always RSA. So in calling ssh in a way where it doesn't use the known_hosts file and doesn't specify host key algorithm in any other way, ssh will fall back to negotiating ECDSA now that GitHub has added support for it. This will give a different key than the RSA key which was previously used.

xCode will interpret this as the RSA key having changed and report this to the user.

There are two major issues with this

  1. xCode is "crying wolf" saying that host identity has changed when it actually hasn't
  2. It is presenting a key fingerprint to the user, which it claims is of an RSA key when it really is of an ECDSA key.

I have reported this as a bug using the feedback assistant.

4 Likes

I have reported this as a bug using the feedback assistant.

Thank you.

What was the bug number?

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

As far as I can tell, it is FB9775066

1 Like

Today, Xcode presented me with a warning message identical to the screenshot shared by Andreas.

This forum post is the only source I can find with a reference to the 7B99811E4C91A50D5A2E2E80133F24CA fingerprint.

Given the popularity of GitHub and Xcode, it would be comforting with an official statement from Apple reassuring that this GitHub fingerprint is valid and that it is not the result of a supply chain attack exploiting MD5 collisions.

I have not heard back regarding my bug report from Apple.

I agree that it is a bit disconcerting. Both that Apple is not reacting, but also that apparently this thread is still the only mention of this which can be found on Google. I am not that well versed in the Apple development ecosystem, but I figure tons of people must be resolving git packages in this way and all most all of those must be hosted on GitHub. I guess many people must have run into this over the past months and just clicked "Trust". Next time I might do the same instead of spending hours on detective work trying to figure out what is going on only to find out that the message is lying to me.

Also, the fact that Xcode developers have decided to use the ssh client in a very non-standard way, replacing the entire (perfectly working) known host check with their own implementation without even bothering to read and understand the RFC.

That being said, you can verify yourself that the reported fingerprint is indeed the MD5 hash of the officially published github.com ECDSA key.

In terms of attacks exploiting md5 collisions, what we are seeing here is an instance of md5 hashes not matching. So I don't think this message makes such an attack any more or less likely than if we hadn't seen this message. Whether md5 is fit for this purpose in the first place, I don't know enough about cryptography to say for sure. All I know is that md5 is generally considered insecure for cryptographic purposes. On the other hand, attacks are not trivial. Giving Apple the benefit of the doubt, maybe there is something about this particular context which makes md5 okay to use. I would be more likely to believe that if they hand't gotten host key verification wrong in the first place, though.

Even disregarding cryptographic considerations, the fact that GitHub does not publish md5 hashes on their website should be enough reason to use (or also use) sha256 hashes. The entire point of the fingerprint is that a user should be able to compare it to officially published ones.

Update:

I heard back from the bug report. According to Apple, this should be fixed in Xcode 13.3.1. They did not provide any further details, except asking me to verify that things now worked.

I have not checked myself, as reproducing this issue on purpose is quite a lot of work. So I have now closed my feedback ticket. If someone is up for this (I think it requires setting up a git remote and fiddling with the SSH configuration across several swift package resolutions) it would be interesting to know what, if anything, has changed.

I cannot find anything regarding this in the release notes, except for this bit for version 13.3:

Xcode now supports using ED25519 public key signatures to perform git operations. You can select an existing ED25519 key from the Accounts tab in Xcode Preferences. (88897990)

This is about the public key signature, not the host key algorithm. Maybe they did more work in this area and did not put every detail in the change log.