O Gatekeeper faz essa verificação automaticamente na primeira vez que você abre um aplicativo baixado, e na maioria das vezes você nunca vê os detalhes — aparece uma caixa de diálogo, você clica para continuar, pronto. Este laboratório é sobre ver o que o Gatekeeper viu: qual desenvolvedor assinou o aplicativo, se essa assinatura está intacta, se o serviço de notarização da Apple a verificou, e o que ele tem permissão para fazer depois de rodar. Todo comando aqui já vem com as ferramentas de linha de comando do Xcode (xcode-select --install caso você ainda não as tenha), e todos eles são apenas leitura — você está inspecionando o aplicativo, não alterando-o.
A assinatura em si: codesign -dvvv
O codesign é a ferramenta da Apple para criar e inspecionar assinaturas de código. A flag -d exibe informações sobre o código assinado em um caminho e, segundo sua página de manual, "níveis crescentes de verbosidade produzem mais saída" — então -dvvv (display, três níveis de verbosidade) traz o quadro completo em um único comando:
codesign -dvvv /Applications/Example.app
# example output, trimmed to the fields that matter
Executable=/Applications/Example.app/Contents/MacOS/Example
Identifier=com.example.app
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=... flags=0x10000(runtime) hashes=...
Signature size=4741
Authority=Developer ID Application: Example Software LLC (ABCDE12345)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Team Identifier=ABCDE12345
Runtime Version=14.0.0Quatro campos para ler sempre. Authority é a cadeia de certificados: um aplicativo externo normal deve terminar em Apple Root CA passando por Developer ID Certification Authority, com a primeira linha nomeando o desenvolvedor. Team Identifier é o identificador de dez caracteres da Apple para a conta de desenvolvedor — o valor a comparar entre aplicativos que você acredita virem da mesma empresa, já que não muda entre os lançamentos dela. flags=0x10000(runtime) significa que o hardened runtime está ativado, um conjunto de restrições adicionais (como resistir à injeção de código no processo) que a Apple exige para a notarização. E a ausência total de qualquer linha Authority — apenas Signature=adhoc — significa que o aplicativo não está assinado ou está autoassinado, sem nenhuma cadeia até a Apple.
A assinatura ainda corresponde aos arquivos: --verify --deep --strict
Uma assinatura é uma promessa sobre um conjunto específico de bytes no momento em que foi assinada. --verify checa se essa promessa ainda se sustenta — segundo a página de manual, ela confirma "que o código nesse(s) caminho(s) está assinado, que a assinatura é válida, e que todos os componentes selados estão inalterados." Duas flags extras importam para um bundle de aplicativo, que é um diretório cheio de recursos aninhados, frameworks e executáveis auxiliares, não um único arquivo:
codesign --verify --deep --strict --verbose=2 /Applications/Example.app
/Applications/Example.app: valid on disk
/Applications/Example.app: satisfies its Designated Requirement--deep importa porque, segundo a página de manual, a verificação de conteúdo aninhado por padrão é "limitada a uma investigação superficial que pode não detectar alterações no código aninhado" — o modo profundo verifica recursivamente todo framework embutido e ferramenta auxiliar, não apenas o bundle externo. --strict acrescenta checagens extras que a Apple considera importantes o suficiente para não vir ativadas por padrão, incluindo que qualquer symlink dentro do bundle "aponte para arquivos selados dentro do seu próprio bundle", rejeitando um que aponte para fora do aplicativo ou para algo não selado — um truque conhecido para contrabandear uma carga não assinada dentro de um bundle assinado de forma legítima. Se qualquer uma das checagens falhar, você verá code failed to satisfy specified code requirement ou uma nota nomeando exatamente qual item aninhado não corresponde ao que foi originalmente selado — leia essa linha, ela nomeia o arquivo.
Lendo os entitlements
Entitlements são as permissões específicas que a assinatura de um aplicativo concede a ele — acesso à câmera, a capacidade de alcançar a rede fora de um sandbox, desativar a validação de bibliotecas, e assim por diante. codesign -d --entitlements - os extrai; segundo a página de manual, "os dados de entitlement embutidos serão extraídos da mesma forma e gravados no" caminho fornecido, e - significa saída padrão:
codesign -d --entitlements - /Applications/Example.app
# example output, trimmed
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>A maioria dos entitlements é comum e corresponde ao que o aplicativo obviamente precisa — um aplicativo de videochamada pedindo acesso à câmera não é um achado. O que vale a pena parar para examinar é o disable-library-validation: significa que o aplicativo vai carregar código de fora do seu próprio bundle assinado, o que é uma necessidade normal para alguns softwares baseados em plugins e uma porta mais larga do que a maioria dos aplicativos precisa. É um detalhe a anotar, não um sinal de alerta automático, e é exatamente o tipo de detalhe que você não consegue ver sem perguntar.
O serviço de notarização da Apple de fato verificou isso: spctl e stapler
Uma assinatura válida só prova que um aplicativo não foi alterado desde que um desenvolvedor o assinou — não diz nada sobre se a Apple já o examinou. É isso que a notarização acrescenta. A própria documentação da Apple descreve o serviço automatizado de notarização como algo que varre "seu software em busca de componentes maliciosos, verifica problemas de assinatura de código e devolve os resultados a você rapidamente." Quando é aprovado, "o serviço de notarização gera um tíquete para você grampear ao seu software; o serviço de notarização também publica esse tíquete on-line, onde o Gatekeeper consegue encontrá-lo."
spctl --assess é a forma prática de pedir o veredito ao próprio mecanismo de política do Gatekeeper, em vez de deduzi-lo por conta própria. Segundo sua página de manual, --assess "realiza uma avaliação sobre os arquivos fornecidos", e -v / --verbose, repetido para mais detalhe, é descrito simplesmente como uma solicitação de "saída mais detalhada":
spctl --assess -vv /Applications/Example.app
/Applications/Example.app: accepted
source=Notarized Developer IDsource=Notarized Developer ID é o resultado que você quer ver — significa que o Gatekeeper encontrou uma assinatura Developer ID válida e um tíquete de notarização, esteja esse tíquete grampeado ao aplicativo ou encontrado on-line. Um resultado de source=Unnotarized Developer ID significa que o aplicativo está assinado, mas a Apple ainda não o notarizou (ou ainda não o fez), e um simples rejected significa que o Gatekeeper o bloquearia de abrir na configuração padrão.
Para checar especificamente o grampeamento (staple), o xcrun stapler validate procura o tíquete fisicamente anexado ao aplicativo, em vez de pedir ao Gatekeeper que o busque on-line — útil para confirmar que um aplicativo ainda será avaliado corretamente sem nenhuma conexão de internet:
xcrun stapler validate /Applications/Example.app
Processing: /Applications/Example.app
The validate action worked!A flag de quarentena: de onde vem a checagem da primeira execução
O guia de Segurança da Plataforma da Apple explica que "o Gatekeeper também rastreia a procedência dos arquivos gravados por software baixado" e "solicita a aprovação do usuário antes de abrir pela primeira vez um software baixado." O mecanismo por trás disso é um atributo estendido, com.apple.quarantine, que o Safari, o Mail e outros aplicativos anexam a qualquer coisa que salvam da rede. xattr -l o lista, e segundo a página de manual, essa opção "faz com que tanto os nomes dos atributos quanto seus valores correspondentes sejam exibidos":
xattr -l ~/Downloads/Example.dmg
com.apple.quarantine: 0081;65e1a2b3;Safari;Nenhuma saída significa que o arquivo não carrega nenhuma flag de quarentena — ou foi criado localmente, ou chegou por um caminho que não define o atributo (algumas ferramentas de arquivo e gerenciadores de pacotes o pulam), ou a flag foi removida manualmente com xattr -d com.apple.quarantine. Esse último caso vale a pena conhecer por outro motivo: é uma forma documentada de contornar por completo a checagem de primeira execução do Gatekeeper, em arquivos nos quais se confia ou se acredita confiar, e vale a pena fazer isso de forma deliberada em vez de colar instruções de terminal vindas de uma fonte desconhecida.
Uma comparação prática: dois aplicativos alegando o mesmo desenvolvedor
Uma forma concreta de usar tudo isso junto: digamos que você tenha duas cópias de um aplicativo que afirmam vir da mesma empresa, uma do site do próprio desenvolvedor e outra de um link que alguém lhe enviou. Rode codesign -dvvv nas duas e compare a linha Team Identifier — é uma string de dez caracteres vinculada a uma conta específica de Apple Developer e, ao contrário de um nome de exibição ou de um identificador de bundle, não é algo que um terceiro consiga reproduzir casualmente sem acesso ao certificado de assinatura daquela conta. Se as duas cópias mostrarem Team Identifiers diferentes, você não está olhando para duas compilações do mesmo aplicativo; está olhando para dois assinantes diferentes, e um deles não é quem o download alegava ser. Siga isso com spctl --assess -vv na cópia suspeita — uma origem de notarização divergente ou ausente na cópia que alega ser idêntica a um original notarizado é a confirmação, não apenas uma pista.
Lendo o quadro completo, e os sinais de alerta reais
- Nenhuma cadeia
Authority, ou uma cadeia que não termina na Apple Root CA — o aplicativo não tem nenhuma identidade responsável de desenvolvedor por trás dele. codesign --verifyfalha, especialmente com uma mensagem nomeando um arquivo aninhado específico — algo dentro do bundle mudou depois de ser assinado.spctl --assessretornarejected, ou o Team Identifier emcodesign -dvvvnão corresponde ao desenvolvedor que você esperava para aquele produto.- Uma flag de quarentena que claramente foi removida de um arquivo que você mesmo não baixou, ou que chegou por um canal incomum (um script, um anexo de e-mail renomeado para parecer outra coisa).
- Entitlements totalmente abertos — acesso completo ao disco, validação de biblioteca desativada, acesso irrestrito à rede — em um aplicativo cujo propósito declarado obviamente não precisa deles.
Nenhuma dessas checagens olha para o que o aplicativo de fato faz depois de estar rodando e conectado à rede — essa é uma pergunta de outro tipo, respondida observando o tráfego dele, não sua assinatura. Uma assinatura limpa e um tíquete de notarização válido são um piso real e significativo: dizem que a Apple viu exatamente esse conjunto de bytes e não encontrou problemas de assinatura de código no momento da checagem. São o começo de confiar em um aplicativo, não o fim disso.
Onde FireAI e HisnLabs entram nessa história
A clean signature and a stapled ticket say an app hasn’t been tampered with since Apple checked it — they say nothing about what it connects to afterward, which is the question FireAI’s per-app rules and on-device review are built to keep answering, signature by signature, connection by connection.
O FireAI é o produto da HisnLabs: um firewall com IA que roda direto no seu Mac. Ele mostra, em linguagem simples, cada conexão que seus aplicativos fazem e deixa você decidir o que sai do seu Mac — a IA roda localmente, então seu tráfego nunca é enviado para nós nem para ninguém. A equipe de pesquisa em segurança da HisnLabs é quem mantém essas decisões confiáveis: cataloga quais domínios são telemetria comum e quais são um serviço de verdade, rastreia o país e a rede por trás de uma conexão e treina o modelo local (o recurso Autopilot) com padrões reais de tráfego, sem que nada disso saia do seu Mac.
Você pode ler as decisões técnicas por trás dele, ou testar o FireAI por 17 dias, em FireAI, da HisnLabs.
