Developer ID signature becomes invalid over time without any file modification on macOS 26.6.2

I am seeing a reproducible Developer ID code-signing issue on an Apple Silicon Mac running macOS 26.6.2. A Universal macOS app and its Quick Look extension (arm64 + x86_64) are signed with a newly issued Developer ID Application certificate using Hardened Runtime and a secure timestamp. Immediately after signing, all verification succeeds, including: codesign --verify --strict --verbose=4

and architecture-specific verification for both arm64 and x86_64. At this point, codesign reports: valid on disk satisfies its Designated Requirement

The expected Developer ID authority chain and TeamIdentifier are present. However, after some time, without modifying the bundle or executable, the exact same Quick Look extension starts failing verification for both architectures: invalid signature (code or signature have been modified)

codesign -d then reports: Authority=(unavailable) Info.plist=not bound

The executable SHA-256, size, and mtime remain unchanged. I also copied the now-invalid extension to a different directory, creating completely new inodes. The copy remains invalid. I verified that:

  • all regular files in the original and copy are byte-for-byte identical
  • executable SHA-256 is identical
  • _CodeSignature/CodeResources is identical
  • there are no hard links (link count is 1)
  • there are no extended attributes anywhere in the extension
  • com.apple.provenance, com.apple.quarantine, and com.apple.FinderInfo are absent
  • copying the bundle to a new inode does not restore signature validity

The affected extension executable currently has: SHA-256: 3b36d1aca258a371311a9c94e93d10606edc184ea120dd252cf230a251c67243

CDHash arm64: 178ff5b7b2cedbed00ec6bc07536d168e22d9ba5

CDHash x86_64: ada914101f5b107704b78958520c904c4f022894

Signing environment Developer ID Team ID: XY2B8MLPV8

The Developer ID Application certificate is newly issued with a new RSA 2048-bit private key. I have also observed the following message in the Security log during signing: CSSMERR_CSP_INVALID_KEYATTR_MASK

No new occurrence of that error is logged when subsequently verifying the already-invalid extension. Troubleshooting already performed I have:

  • issued a completely new Developer ID Application certificate with a new RSA 2048-bit private key
  • verified the certificate chain and code-signing policy successfully
  • reproduced related Keychain/identity problems in a fresh macOS user account
  • tested with a newly created independent Keychain
  • tested in Safe Mode
  • reinstalled macOS without erasing user data

Before reinstalling macOS, even security find-identity -v -p codesigning eventually failed to recognize otherwise valid Developer ID identities. After reinstalling macOS, security find-identity -v -p codesigning correctly reports all identities again. I then performed a durability test using the new Developer ID identity on a minimal Universal Mach-O binary. Verification succeeded:

  • immediately after signing
  • after approximately 2 minutes
  • after approximately 5 minutes
  • after copying the binary to a different directory

The minimal binary remained valid throughout. However, the problem subsequently reproduced with the actual Quick Look extension. Notarization The application was packaged in a Developer ID Installer-signed PKG and submitted to Apple Notary Service. The submission was Accepted, stapling and validation succeeded, and Gatekeeper accepted the notarized PKG. Notarization submission ID: 54dc0de7-5089-4b8c-9c10-b5a74df8df97

I initially suspected the packaging process, but I subsequently found that the original pre-PKG Quick Look extension itself had become invalid. Therefore, this does not appear to be caused by PKG creation or extraction. Questions What could cause a Developer ID signature that initially verifies successfully to become invalid later when the signed files themselves have not changed? Is there a Security.framework / codesign diagnostic that can show exactly which part of the CMS signature or CodeDirectory validation is failing? Are there any known macOS 26.x issues involving code-signing validation or CSSMERR_CSP_INVALID_KEYATTR_MASK that could explain this behavior? I would be happy to collect additional Security logs, codesign diagnostics, or a sysdiagnose if that would help identify the cause.

Answered by marucello in 908312022

I completed another Documents-directory test with the sysdiagnose procedure ready in case the problem reproduced. It did not reproduce. T0 was 2026-10-07 20:23:34 JST. Immediately after signing, the app and extension both passed default, arm64, and x86_64 strict verification. I then checked both approximately once per minute for 30 minutes; all 30 checks succeeded. The full six verification cases also succeeded again at 30 minutes. There were no changes to SHA-256 hashes, sizes, inode numbers, link counts, mtimes, or complete regular-file manifests. Interestingly, unlike my previous test, the signing information also remained completely normal from T0 through 30 minutes:

Authority=Developer ID Application: [redacted] (XY2B8MLPV8)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
TeamIdentifier=XY2B8MLPV8
flags=0x10000(runtime)

Secure timestamps were also displayed normally. CSSMERR_CSP_INVALID_KEYATTR_MASK again occurred 12 times during signing, but there were no occurrences after T0. Despite those log entries, the resulting signatures remained fully valid throughout the test. Because the invalid state did not occur, I did not trigger sysdiagnose. I have the procedure ready and will trigger it immediately if the problem reproduces. At this point I have not been able to reproduce the delayed invalidation again since updating the host to macOS 26.7.1 (25G241).

Hmmm, you’ve tried a lot of things but AFAICT you didn’t try the first thing that I would’ve tried, namely copying the app to a different Mac to see if it verifies there. Did you try that? If so, what were the results?

If you didn’t try it, please do that now and let me know what you get back. I recommend that you use a newly installed virtual machine for this test, because that way you can repeat the test by restoring the VM to a ‘clean’ snapshot, one that’s never seen your app previously, between each test.

Note that you don’t have worry about Gatekeeper here, your key test — running codesign --verify — doesn’t care about the Gatekeeper state of the code. So, you can just zip up the failing up, copy it across to the VM, unzip, and try to verify its code signature.


I have also observed the following message in the Security log during signing: CSSMERR_CSP_INVALID_KEYATTR_MASK

What was the full text of that log message?

I’m curious because I’ve been chasing a this problem and I’m starting to suspect a key usage issue in that case.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks. I don't have access to a second physical Mac, so I have now installed a clean macOS VM specifically to perform the test you suggested. However, I discovered something interesting before I could perform the test. Yesterday I made an independent copy of the failing Quick Look extension. At that time, both the original and the copy failed codesign --verify --strict, including architecture-specific verification for both arm64 and x86_64. I also verified that the copy was byte-for-byte identical, had a different inode, contained no hard links or extended attributes, and had identical executable and CodeResources hashes. Today, without modifying that copied extension, the exact same copy now verifies successfully:

valid on disk
satisfies its Designated Requirement

for the default verification as well as both arm64 and x86_64. I checked the other Developer ID-signed copies that I still have, and they currently verify successfully as well. So at the moment I no longer have a specimen that is failing on the host Mac. This appears to show that the verification state can change from invalid back to valid without intentionally modifying the signed code. I have the clean macOS VM ready now. As soon as the failure reproduces again, I will immediately ZIP the failing specimen, copy that ZIP to the clean VM, and run the same codesign --verify there before doing any further troubleshooting. I'll report the host and clean-VM results when I have a failing specimen again.

Thanks — I performed the test you suggested, and the result is quite interesting. I created a clean macOS VM that had never seen the app before. No Apple Developer certificates or Xcode were installed in the VM. Before transferring anything to the VM, I reproduced the failure again on the host Mac with a freshly signed build. The timeline on the host was:

  • 19:58:09 JST: the app and its Quick Look extension both verified successfully with codesign --verify --strict, including separate arm64 and x86_64 verification.
  • 20:03:42 JST: the same app and extension both failed verification for arm64 and x86_64 with:
code or signature have been modified

At that point codesign -d also reported:

Authority=(unavailable)
Info.plist=not bound

I verified that the signed files had not changed during that interval. The complete file manifests for both the app and extension were identical, and the executable SHA-256, size, inode, link count, mtime, and _CodeSignature/CodeResources SHA-256 were unchanged. I stopped at that point without re-signing the app. I then zipped that failing app and copied the ZIP to the clean VM. Before extracting it, I verified the ZIP SHA-256 on the VM against the hash recorded on the host:

a7b652edeb3f17478bc7f4ba99a622ab6d67422a92218d1251e0a5931e36b0a5

The hashes matched. I extracted the ZIP locally on the VM and ran:

codesign --verify --strict --verbose=4
codesign --verify --strict --verbose=4 --arch arm64
codesign --verify --strict --verbose=4 --arch x86_64

against both the app and its Quick Look extension. All six verifications succeeded on the clean VM:

valid on disk
satisfies its Designated Requirement

I left the extracted app untouched and repeated the same six verification tests approximately 10 minutes later. All six still succeeded. So the same signed app that was consistently reported as invalid on the host Mac verifies as valid on a clean macOS VM, both immediately after transfer and again after 10 minutes. This seems to indicate that the signature itself is intact and that the failure is specific to the code-signing validation state on the host Mac. What would you recommend checking next on the host? I can collect Security logs, run specific codesign or Security.framework diagnostics, or provide a sysdiagnose while the host is in the failing state.

This seems to indicate that … the failure is specific to the code-signing validation state on the host Mac.

Yep.

Do you have any third-party security products installed on your main Mac? When I’ve see problems kinda like this in the past I’ve found that the developer was working in a managed environment, and their organisation’s endpoint security product had some unexpected side effects.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yes. I checked, and I do have Intego NetBarrier installed on the main Mac. systemextensionsctl list shows the following active third-party system extension:

TCG22P5KE4
com.intego.app.netbarrier.firewall.extension (10.9.40/995)
NetBarrier Extension
[activated enabled]

There is also an older version (10.9.38/988) in the state:

[terminated waiting to uninstall on reboot]

The Mac is not managed:

Enrolled via DEP: No
MDM enrollment: No

This is my personal Mac, not an organisation-managed environment. I had not considered NetBarrier as a possible factor in the code-signing issue. Would you recommend that I completely uninstall Intego/NetBarrier and reboot before doing the next signing and verification test?

I performed the clean-VM test you suggested, and the result is quite clear. I reproduced the failure again on the host Mac with a newly signed build. Immediately after signing, both the app and its Quick Look extension verified successfully with codesign --verify --strict, including separate arm64 and x86_64 verification. Approximately five minutes later, without modifying any files, both the app and extension failed verification on the host with:

code or signature have been modified

and codesign -d reported:

Authority=(unavailable)
Info.plist=not bound

SHA-256 manifests taken immediately after signing and after the failure were identical. I stopped at that point without re-signing, packaging, or notarizing the build, and archived the failing signed app using ditto. I then copied that ZIP to a newly installed macOS VM which had never seen the app before. The VM is running the exact same OS version as the host:

macOS 26.6.2
Build 25G83

The ZIP SHA-256 before testing in the VM was:

adb286fed8205c12e17c09f2ffa6109afb5ee4771c2690c03701be707fb5c24a

which matched the ZIP created on the host. On the clean VM, the exact same signed app verifies successfully:

MatFrame Composer.app: valid on disk
MatFrame Composer.app: satisfies its Designated Requirement

This succeeds for default verification, arm64, and x86_64. The embedded Quick Look extension also verifies successfully for all three:

MatFrameQuickLook.appex: valid on disk
MatFrameQuickLook.appex: satisfies its Designated Requirement

So the same signed code that fails verification on the host Mac verifies successfully in a clean VM running the same macOS build. Regarding your question about third-party security software: I checked and found that Intego NetBarrier is installed on the host. systemextensionsctl list shows:

TCG22P5KE4
com.intego.app.netbarrier.firewall.extension (10.9.40/995)
NetBarrier Extension
[activated enabled]

There is also an older 10.9.38 extension in:

[terminated waiting to uninstall on reboot]

The Mac is not DEP or MDM enrolled; it is my personal Mac. For this latest signing test I turned NetBarrier protection off in its UI before signing. The signature failure still reproduced after approximately five minutes. However, systemextensionsctl continued to show the NetBarrier extension as [activated enabled], so I don't think this test rules NetBarrier out. Would you recommend completely uninstalling Intego/NetBarrier and rebooting the host before repeating the signing test?

Would you recommend completely uninstalling Intego/NetBarrier and rebooting the host before repeating the signing test?

Yes.

To be clear, I’ve no specific evidence that this is the issue, just that it helps isolate the problem. We have one machine (your main Mac) that exhibits the issue and another machine (your test VM) that doesn’t, so we want to bring those closer together to converge on the cause.

Another approach that might help would be to install this software on your test VM.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I performed the A/B test after completely uninstalling Intego/NetBarrier and rebooting the Mac. Before starting the test:

systemextensionsctl list
0 extension(s)

Unfortunately, the same problem reproduced. I created a newly signed build using the same Developer ID Application identity. Immediately after signing (20:31:16 JST), both the app and Quick Look extension verified successfully with:

  • default verification
  • arm64 verification
  • x86_64 verification

The authority chain, Team ID, Hardened Runtime, secure timestamp, and extension entitlements were all correct. At 20:37:17, approximately six minutes later, both the app and extension failed all three verification tests with:

code or signature have been modified

and codesign -d reported:

Authority=(unavailable)
Info.plist=not bound

I verified that the files had not changed during that interval. The executable and CodeResources SHA-256 hashes were unchanged, the complete regular-file manifests were identical, and size, inode, link count, and mtime were unchanged. I stopped immediately after reproducing the failure and did not re-sign, package, or notarize the build. So removing NetBarrier and its System Extension did not prevent the issue. It appears that NetBarrier is not a necessary condition for the signature verification failure. I still have this exact failing signed app preserved, as well as the clean macOS VM where the previous failing specimen verified successfully. Would you like me to copy this new failing specimen to the clean VM as well, or is there another diagnostic you would prefer me to run on the host while it is in the failing state?

OK, I’m glad we ruled that out.

And with that, I have a question and a request.


Are these files stored on an Apple file system? That is, APFS or HFS Plus?

And in a location that’s not shared by a cloud sync service? This includes third-party ones, but also iCloud Drive, and specifically the Desktop and Documents folder when you have synching enabled (per System Settings > YOUR_APPLE_ACCOUNT > iCloud > Drive > Desktop & Documents Folders).

I’ve seen cases like this where the underlying cause was a file system problem. Your earlier tests put a limit on how this problem could be expressed, but I still wanna rule this out completely.


Earlier you wrote:

three verification tests [failed] with: code or signature have been modified

If you run codesign with the -v flag, it should tell you what was modified. For example:

% codesign -v --deep --strict -v QProcessDock.app                 
QProcessDock.app: valid on disk
QProcessDock.app: satisfies its Designated Requirement
% cp /dev/null QProcessDock.app/Contents/Resources/AppIcon.icns
% codesign -v --deep --strict -v QProcessDock.app                 
QProcessDock.app: a sealed resource is missing or invalid
file modified: /Users/quinn/Test/QProcessDock.app/Contents/Resources/AppIcon.icns

What do you get in this case? And is it consistent?

If you don’t see anything useful with -v, add some more (-:

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The host startup volume is APFS:

Volume Name: Macintosh HD
File System Personality: APFS
Type (Bundle): apfs

The files are under my local Documents folder, but iCloud Drive's "Desktop & Documents Folders" option is disabled. The Documents folder is therefore not being synced by iCloud Drive. I am also not intentionally using any third-party cloud sync service for this project. There is another interesting complication: the exact specimen that failed verification on October 5 has now returned to a valid state, without me intentionally modifying or re-signing it. I ran:

codesign --verify --deep --strict -vvvvv "MatFrame Composer.app"

and the embedded extension was prepared and validated successfully. The app then reported:

MatFrame Composer.app: valid on disk
MatFrame Composer.app: satisfies its Designated Requirement

I also ran codesign --verify --strict -vvvvv directly on the Quick Look extension, and it is currently valid as well. So unfortunately I cannot capture the detailed verbose failure output from this specimen at the moment. Its verification state has now changed from valid immediately after signing, to invalid approximately six minutes later, and then back to valid again, without any intentional modification. The next time it enters the invalid state, I will immediately run verbose verification on both the app and extension before doing anything else and report the complete output.

I completed the additional diagnostic test. This time I created and signed a fresh build entirely under /private/tmp, on the local APFS Data volume (/dev/disk3s1, mounted at /System/Volumes/Data), with no cloud-synced directory involved. systemextensionsctl list reported:

0 extension(s)

One important difference I noticed during this test is that the host is now running macOS 26.7.1 (25G241). The earlier reproductions were on macOS 26.6.2 (25G83). The app and Quick Look extension both verified successfully immediately after signing, for default, arm64, and x86_64 verification. I then verified both once per minute for 30 minutes. Every verification returned exit status 0. At the 30-minute point, both the app and extension still passed default, arm64, and x86_64 verification. The SHA-256 hashes, sizes, inode numbers, link counts, mtimes, and complete regular-file manifests were unchanged between immediately after signing and 30 minutes later. So the delayed signature invalidation did not reproduce in this test. There is one other potentially interesting result. During signing, the Security log recorded 12 occurrences of:

CSSMERR_CSP_INVALID_KEYATTR_MASK

The final occurrence was at 20:16:18.735338 JST. There were no new occurrences after signing completed or during the 30-minute monitoring period. Thus, in this test, CSSMERR_CSP_INVALID_KEYATTR_MASK occurred during signing even though the resulting signatures remained valid for the entire 30-minute observation period. Because both the storage location and the OS version differ from my earlier reproductions, I don't think this test by itself tells us whether the change is due to using /private/tmp, the update from macOS 26.6.2 to 26.7.1, or some other host-state difference. Would you recommend that I next repeat the same test from my normal local Documents project location on macOS 26.7.1, so that the storage location is the main variable?

I repeated the Documents-folder test, this time making sure that no verification or diagnostic operation started until all signing processes had completely finished. The host is now macOS 26.7.1 (25G241), with 0 extension(s). I defined T0 as the point where signing of both the app and extension had completed successfully with exit status 0:

T0: 2026-10-06 21:36:27 JST

Immediately after T0, strict verification succeeded for both the app and Quick Look extension in all six cases: default, arm64, and x86_64. I then verified both approximately once per minute for 30 minutes. All 30 checks succeeded. At 30 minutes, detailed strict verification again succeeded for default, arm64, and x86_64 for both bundles. There were no changes to SHA-256 hashes, sizes, inode numbers, link counts, mtimes, or complete regular-file manifests. So on macOS 26.7.1 I have now had two 30-minute tests without the delayed verification failure:

  • /private/tmp on local APFS: remained valid for 30 minutes
  • my local Documents folder on the same APFS Data volume: remained valid for 30 minutes

However, I noticed something else that may be important. From immediately after T0 through the end of the 30-minute test, codesign -d --verbose=4 consistently reported for both the app and extension:

Authority=(unavailable)
Info.plist=not bound
TeamIdentifier=XY2B8MLPV8
flags=0x10000(runtime)

Strict verification nevertheless continued to succeed throughout the test. I also could not see the secure timestamp in this display output. CSSMERR_CSP_INVALID_KEYATTR_MASK occurred 12 times during signing, but there were no new occurrences after T0. So while the delayed codesign --verify failure did not reproduce, I am not sure whether this Developer ID signature should be considered completely healthy given the persistent Authority=(unavailable) and Info.plist=not bound output. Also, the earlier delayed failures occurred on macOS 26.6.2 (25G83), whereas these two stable 30-minute tests were performed after the host had updated to macOS 26.7.1 (25G241). Does the persistent Authority=(unavailable) / Info.plist=not bound output indicate a problem even though strict verification succeeds? And would you recommend any specific diagnostic to determine why the signing information is not being displayed normally?

Would you recommend that I next repeat the same test from my normal local Documents project location on macOS 26.7.1 … ?

Yeah, that seems like a good next step.

This is such a weird problem. Hopefully it’ll come back when you retest with the Documents directory, because I don’t think there will be any way to work out what’s being going wrong otherwise.

Oh, and if you do manage to reproduce this, immediately trigger a sysdiagnose log and save that log somewhere. Depending on how this pans out that log may or may not be useful, but it’s good to grab one just in case.

For more info about sysdiagnose logs, see Bug Reporting > Profiles and Logs.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I completed another Documents-directory test with the sysdiagnose procedure ready in case the problem reproduced. It did not reproduce. T0 was 2026-10-07 20:23:34 JST. Immediately after signing, the app and extension both passed default, arm64, and x86_64 strict verification. I then checked both approximately once per minute for 30 minutes; all 30 checks succeeded. The full six verification cases also succeeded again at 30 minutes. There were no changes to SHA-256 hashes, sizes, inode numbers, link counts, mtimes, or complete regular-file manifests. Interestingly, unlike my previous test, the signing information also remained completely normal from T0 through 30 minutes:

Authority=Developer ID Application: [redacted] (XY2B8MLPV8)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
TeamIdentifier=XY2B8MLPV8
flags=0x10000(runtime)

Secure timestamps were also displayed normally. CSSMERR_CSP_INVALID_KEYATTR_MASK again occurred 12 times during signing, but there were no occurrences after T0. Despite those log entries, the resulting signatures remained fully valid throughout the test. Because the invalid state did not occur, I did not trigger sysdiagnose. I have the procedure ready and will trigger it immediately if the problem reproduces. At this point I have not been able to reproduce the delayed invalidation again since updating the host to macOS 26.7.1 (25G241).

I have not been able to reproduce the delayed invalidation again since updating the host to macOS 26.7.1 (25G241).

OK. In that case I think we should draw a line under this. Lemme know if you see anything like this again [1].

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Keeping in mind the old saying that “Bugs that mysteriously disappear can just as easily mysteriously reappear.” |-:

Thank you very much for your help and guidance throughout this investigation. I agree that we can close this investigation for now. If the issue occurs again, I'll capture a sysdiagnose immediately and report back with the relevant logs. I really appreciate your time and support.