Opened 2 months ago

Last modified 7 weeks ago

#66749 new enhancement

Add SecTrustEvaluateWithError to allow Go binaries built with 1.19+ to run on older systems

Reported by: krackers Owned by:
Priority: Normal Milestone:
Component: ports Version:
Keywords: Cc: cjones051073 (Chris Jones), kencu (Ken)
Port: legacy-support


Since the change Go now calls into libSecurity's SecTrustEvaluateWithError for certificate validation. As a result, even with a legacySupport dylib injected to shim the missing libc functions Go needs, because SecTrustEvaluateWithError is present only on 10.14+, binaries will still refuse to run on older versions.

Older versions do have a SecTrustEvaluate which does the same validation but returns its output in a slightly different format. Hence it should not be too hard to write a wrapper.

This would also resolve

Change History (2)

comment:1 Changed 2 months ago by jmroot (Joshua Root)

Cc: cjones051073 kencu added

comment:2 Changed 7 weeks ago by krackers

I think something like the below should work.

CFStringRef getStringForResultType(SecTrustResultType resultType) {
	switch (resultType) {
		case kSecTrustResultInvalid: return CFSTR("Error evaluating certificate");
		case kSecTrustResultDeny: return CFSTR("User specified to deny trust");
		case kSecTrustResultUnspecified: return CFSTR("Rejected Certificate");
		case kSecTrustResultRecoverableTrustFailure : return CFSTR("Rejected Certificate");
		case kSecTrustResultFatalTrustFailure :return CFSTR("Bad Certificate");
		case kSecTrustResultOtherError: return CFSTR("Error evaluating certificate");
		case kSecTrustResultProceed: return CFSTR("Proceed");
		default: return CFSTR("Unknown");
	return CFSTR("Unknown");

bool CustomSecTrustEvaluateWithError(SecTrustRef trust, CFErrorRef  *error) {
	SecTrustResultType trustResult = kSecTrustResultInvalid;
	OSStatus status = SecTrustEvaluate(trust, &trustResult);
	if (status == errSecSuccess && (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified)) {
		if (error) {
			*error = NULL;
		return true;
        if (error)
	    *error = CFErrorCreate(kCFAllocatorDefault, getStringForResultType(trustResult), 0, NULL);
	return false;

This may not work for any application that does logic based on the actual error code (I briefly looked and it seemed tricky to get this via private APIs). But for go at least, this should work.

Last edited 7 weeks ago by krackers (previous) (diff)
Note: See TracTickets for help on using tickets.