Thanks for the reply 🙏🏽
"I’m not really sure how to respond to your original post"
Understandable if this isn't something you can't confirm, but really was just looking for a confirmation from Apple that:
This is a known (macOS 15) issue
Something changed in the Network Extension API/subsystem (requiring updates too 3rd-party tools)
None of the above (meaning, a bug in LuLu)
My goal of this post, was also to help Apple understand this appears to be a widespread issue, as at this point I'm confident it's #1, as this is something impacting everybody who utilizes a network filter 🫠 I've seen tech reports/bulletins from CrowdStrike, ESET, Microsoft Defender and many others (VPNs, etc). I'm not able to post the links here, but a search on Reddit, or in the "Mac Admins" Slack Channel will quickly pull them up.
Post
Replies
Boosts
Views
Activity
Bug Report: FB13657781
Alternately (as noted in the writeup on the Objective-See site), the issue could also be due the fact that the grade method is simply invoked with the wrong grades.
The ones passed in, (in source code named “launchArchs”) are initialized via a call to forCurrentOS which returns just GRADE_arm64e:
const GradedArchs* launchArchs = &GradedArchs::forCurrentOS(false, false);
However, if Apple had instead invoked GradedArchs::launchCurrentOS, it would return launch_AS:
const GradedArchs GradedArchs::launch_AS = GradedArchs({GRADE_arm64e, 3}, {GRADE_arm64, 2}, {GRADE_x86_64, 1});
As this contains grades for arm64e, arm64, and x86_64 when grade is invoked, 3rd-party universal binaries would be processed correctly with the arm64 Mach-O being identified as both valid, and as the best slice.
The solution is to use the undocumented SecAssessmentTicketLookup API, with the cdhash of the item. However, there are a few nuances to be aware of (that tripped me up), such as making sure to specify the right SecCSDigestAlgorithm ...which is a bit tricky as the cdhash can be truncated!
This is what worked for me:
Obtain a SecStaticCodeRef or SecCodeRef for the item, for example via SecStaticCodeCreateWithPath.
Obtain the code signing dictionary via SecCodeCopySigningInformation.
Iterate over the code directory hashes found in the cdhashes key of the code signing dictionary.
For each cdhash, pass to the undocumented SecAssessmentTicketLookup API. It appears that the hashType should be set to kSecCodeSignatureHashSHA256 even though the hash length may be 20 (which is the length of SHA-1 hash CC_SHA1_DIGEST_LENGTH). In other words it appears to the hash is truncated. For the flag, SecAssessmentTicketFlags parameter, pass kSecAssessmentTicketFlagForceOnlineCheck
If SecAssessmentTicketLookup returns EACCES, this means the item has been revoked.
Additional info:
SecAssessmentTicketLookup function definition:
Boolean SecAssessmentTicketLookup(CFDataRef hash, SecCSDigestAlgorithm hashType, SecAssessmentTicketFlags flags, double *date, CFErrorRef *errors);
Example of Apple code (file: notarization.cpp) that implements this in libsecurity_codesigning:
bool checkNotarizationServiceForRevocation(CFDataRef hash, SecCSDigestAlgorithm hashType, double *date)
{
bool is_revoked = false;
secinfo("notarization", "checking with online notarization service for hash: %@", hash);
#if TARGET_OS_OSX
CFRef<CFErrorRef> error;
if (!SecAssessmentTicketLookup(hash, hashType, kSecAssessmentTicketFlagForceOnlineCheck, date, &error.aref())) {
CFIndex err = CFErrorGetCode(error);
if (err == EACCES) {
secerror("Notarization daemon found revoked hash: %@", hash);
is_revoked = true;
} else {
secerror("Error checking with notarization daemon: %ld", err);
}
}
#endif
return is_revoked;
}
Hooray this is now fixed in macOS 13.3 🙏🏽