Mac OS Gatekeeper阻止已签名的命令行工具

4
我在Xcode中有一个“命令行工具”目标(不是应用程序包),它被Gatekeeper阻止了。多年来,我一直将此工具用作我的PostCheck通讯录插件的简单安装程序。

2012年,我使用我的Apple开发人员ID签名了该工具,以便Gatekeeper不会阻止它,一切都很顺利。现在我注意到,在macOS Sierra(10.12)下它被阻止了,并且在测试期间,我还发现它也被10.11.6阻止。(当我说被阻止时,我指用户必须右键单击它并选择“打开”,而不是在警告对话框中给出选项。)它仍然可以在10.11.2上正常工作! – 如果我没记错,Mac OS X 10.11.4有一个错误,即使已经签名,也会阻止非应用程序包。但我认为这个问题在10.11.5中得到了修复。也许它相关呢?

我已尝试使用Sierra下的Xcode 8重新编译和重新签署可执行文件。我尝试在二进制文件中嵌入Info.plist(这之前我没有做过)。我尝试进行存档而不仅仅是“构建”,以防止出现调试与发布配置的问题。我已经花了两天时间搜索验证可执行文件是否正确签名的方法,结果看似相互矛盾……

有这个:

codesign --verify --verbose <executable> 
<executable>: valid on disk
<executable>: satisfies its Designated Requirement

还有这个:

spctl --assess --verbose <executable> 
<executable>: rejected (the code is valid but does not seem to be an app)
source=matched cdhash

还有这个:

spctl -a -v --raw <executable> 
<executable>: accepted
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>assessment:authority</key>
    <dict>
        <key>assessment:authority:flags</key>
        <integer>0</integer>
        <key>assessment:authority:source</key>
        <string>allowed cdhash</string>
        <key>assessment:authority:weak</key>
        <true/>
    </dict>
    <key>assessment:cserror</key>
    <integer>-67002</integer>
    <key>assessment:remote</key>
    <true/>
    <key>assessment:verdict</key>
    <true/>
</dict>
</plist>

我想我的问题的一部分是我不知道经过有效的苹果开发者ID签名后的命令行可执行文件应该看起来像什么。而且我也不知道是否这是macOS的问题,我无法做任何事情。同时,要在谷歌上找到与代码签名Unix命令行可执行文件相关的信息也非常困难。

如果您能提供任何有关此问题的见解,我将不胜感激。谢谢!


尝试在codesign中使用--strict选项。另外,尝试在spctl中使用-t open选项,因为双击可执行文件并不会直接执行它,而是将其作为文档传递给终端,终端将路径作为命令执行。这可能会解决“似乎不是应用程序”的问题。您还可以多次指定-v以增加详细程度。使用--ignore-cache只是为了确保您正在评估新文件。 - Ken Thomases
1
值得一提的是,错误代码cserror -67002是errSecCSNotAppLike(这可能并不令人意外)。我通过创建一个包含基本上是命令行工具的应用程序包并对其进行签名来“修复”它。然后我可以运行命令行工具,并只需将其引用为foo.app/Contents/MacOS/foo。虽然用户体验不是很好,但对我的需求有效。 - dmaclach
3个回答

4

我很不情愿回答我的问题,但以防万一有人遇到同样的问题:

解决方法是将命令行工具分发在签名磁盘映像中,而不是在zip文件中。

我最终测试到10.11.4并确认那时问题开始出现。(当时我可能测试不正确。)无论我如何签名,OS X都会阻止双击Unix命令行工具。这可能是为了最好的结果,因为大多数命令行工具将从Terminal.app中运行。

对于Sierra,结果证明我需要签署DMG,以绕过Gatekeeper的新路径随机化功能。


似乎在Catalina版本中,“公证”可能会使这个问题“僵尸般地”复活,而且在这种情况下,似乎(至少在我的情况下)将可执行文件作为签名和公证的DMG文件的一部分可能无法解决问题。 - John Clements
1
为了记录,我自己回答一下:在我的情况下,问题可能是可执行文件加载了另一个库,因此即使两者都经过了公证,运行加载库的可执行文件也是不行的。 - John Clements
我也发现Catalina会阻止链接相对加载器路径的.dylib命令行工具(即otool -L /path/to/libFoo.dylib在某处输出@executable_path,因为该库是使用DYLIB_INSTALL_NAME_BASE=@executable_path构建的)。可能的解决方法包括:1)删除相对加载器路径(指定/usr/local/bin而不是@executable_path),2)从签名的.pkg中打包和安装它们,以避免用户下载您的分发时设置隔离标志,3)将可执行文件和库分发到一个捆绑包中,并从那里运行CLI工具。 - Bill Feth

1
在 macOS Catalina 10.15.3 及更早版本中存在已知 bug(已在 10.15.4 中修复),其中链接到其包外的 .dylib 的经过公证的命令行应用程序(命令行应用程序通常不在包中)将仍然无法通过 Gatekeeper 检查,当设置了命令行可执行文件上的隔离标志时会触发该检查。
为解决此问题,Apple DTS 建议:
最简单的解决方法是使用硬化运行时和库验证标志签署您的工具。
也就是说,将您对 codesign 的调用从此:
% codesign -s …stuff… -o runtime …stuff… helloworld
更改为此:
% codesign -s …stuff… -o runtime,library …stuff… helloworld
显式设置库标志将禁用此 Gatekeeper 检查,并允许您的工具在 macOS 10.15.{0,1,2,3} 上运行。请注意,在 10.15.4 发布并广泛采用后,请记得删除此标志。
每当您通过互联网下载或AirDrop接收文件时(但不是通过网络文件共享或iCloud Drive),隔离标志都会被设置,详见https://eclecticlight.co/2019/10/24/airdrop-and-quarantine-flags/

1

当我使用go-astilectron-bundler进行打包时,我遇到了同样的问题,在我的情况下需要添加以下内容:

<key>CFBundlePackageType</key>
<string>APPL</string>

Info.plist文件添加到解决方案中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接