8 min de leitura

Quando as atualizações de binários de agentes devem perder a confiança?

As atualizações de binários de agentes exigem uma nova decisão de confiança. Aprenda a verificar a assinatura do macOS, a procedência do editor, o contexto do processo e o acesso.

Quando as atualizações de binários de agentes devem perder a confiança?

Uma aprovação para um agente local deve valer para o executável que você examinou, no processo que aprovou e para o acesso solicitado naquele momento. Quando o executável muda, a aprovação antiga expirou na prática, mesmo que o nome do arquivo, o identificador do pacote e o ícone continuem iguais.

Isso parece rigoroso até você investigar uma aprovação concedida à versão 1.8 e usada discretamente pela versão 1.9. Muitas decisões ruins começam com uma verificação de identidade ampla demais: um caminho, o nome do produto ou um Team ID de assinatura conhecido. Essas verificações podem fornecer evidências. Nenhuma delas deve, sozinha, manter uma confiança privilegiada depois de uma mudança no código.

A confiança pertence a um executável observado

Um agente local não é uma identidade de editor. É um programa assinado específico, carregado em um caminho determinado, com um processo pai, argumentos, ambiente e conjunto de ações solicitadas específicos. Um editor pode lançar muitos programas. Um programa pode mudar bastante entre versões. Um nome estável diz muito pouco sobre qualquer um desses fatos.

Essa distinção é mais importante quando o agente pode chamar APIs pagas, usar credenciais SSH, alterar um repositório ou enviar dados para fora da máquina. Uma aprovação não é um elogio ao fornecedor. É uma permissão para que um processo execute ações com consequências.

Mantenha estas identidades separadas:

  • A identidade do arquivo é o código assinado e seu digest no disco.
  • A identidade de assinatura é a autoridade que o macOS informa para esse código.
  • A procedência do editor é a evidência de que o arquivo chegou pelo caminho de lançamento esperado.
  • A identidade em tempo de execução inclui o processo que o iniciou e o acesso que ele pede para usar.

As equipes costumam juntar as quatro em «este é o nosso agente». É assim que uma substituição no mesmo caminho herda um acesso que nunca mereceu. A regra segura é simples: a substituição de um executável inicia uma nova decisão de confiança.

Um hash detecta uma substituição, mas não informa quem assinou o substituto. Uma assinatura identifica um signatário, mas não prova o canal de download. Um download limpo não mostra se a nova versão precisa de acesso mais amplo. Você precisa das três verificações porque cada uma detecta uma falha diferente.

Não cometa o erro oposto de fixar cada byte para sempre. As compilações mudam legitimamente, os certificados são renovados e as versões precisam de atualizações. O objetivo não é a permanência. É garantir que alguém veja a mudança, estabeleça o que mudou e decida explicitamente se a autoridade solicitada ainda faz sentido.

A assinatura de código responde a uma pergunta mais limitada do que muita gente imagina

A assinatura de código do macOS permite que o sistema operacional verifique se o código assinado não mudou desde que o signatário produziu a assinatura. Na distribuição Developer ID, o Gatekeeper também avalia a identidade do desenvolvedor e sua avaliação do item. Isso é uma evidência útil. Não é um veredito completo sobre a cadeia de fornecimento.

A Technical Note TN2206 da Apple, «macOS Code Signing In Depth», separa a identidade do código das condições mais amplas sob as quais o sistema aceita um código. A discussão sobre requisitos designados é especialmente relevante aqui: o macOS pode usar um requisito para reconhecer uma versão futura como pertencente à mesma identidade de código. Essa continuidade ajuda nas atualizações comuns de aplicativos. Ela é fraca demais como única condição para um agente que pode gastar dinheiro ou usar infraestrutura privada.

Uma assinatura válida não responde a estas perguntas:

  • O editor pretendia que exatamente esta versão chegasse à sua máquina?
  • Uma credencial de lançamento comprometida do editor assinou o arquivo?
  • A nova versão adicionou uma capacidade que muda seu risco?
  • Um instalador, atualizador ou script de inicialização substituiu um componente sem alterar a parte que você verificou?

O Gatekeeper e a notarização reduzem a chance de o macOS executar um software claramente não confiável. Eles não transformam um agente assinado corretamente em um detentor aprovado da sua autoridade operacional. Trate a admissão pelo sistema operacional e a aprovação de ações privilegiadas como decisões separadas.

O mesmo vale para a renovação de um certificado. Um certificado renovado pode ser um evento administrativo normal. Ainda assim, ele muda as evidências nas quais você se baseia. Se o Team ID, o identificador e o caminho esperado do editor continuarem consistentes, um operador pode aprovar a atualização depois da revisão. Se a autoridade de assinatura passar para outra organização, pare e procure uma explicação clara do editor. Não aceite uma mudança inesperada de identidade só porque o aplicativo abre sem mostrar um aviso.

A procedência do editor é separada da assinatura

A procedência pergunta como o binário chegou até você e se esse caminho corresponde à prática normal de lançamento do editor. A assinatura de um arquivo copiado de um anexo desconhecido em um chat informa quem assinou aquela cópia. Ela não explica por que você a recebeu ali.

Para um agente de produção, registre um pequeno comprovante da versão quando instalá-lo ou atualizá-lo. Pode ser um arquivo de texto no repositório que gerencia o agente, um registro de alterações ou uma entrada em um diário interno de versões. O comprovante deve registrar a versão, a origem da instalação, a autoridade de assinatura observada, o Team ID, o digest, a data da revisão e a pessoa que o aceitou. Se o editor fornecer um digest da versão, registre-o também.

O canal de lançamento merece uma verificação humana de bom senso. O atualizador veio do aplicativo esperado? O editor publicou notas de versão para esta versão? O nome do arquivo, a assinatura do pacote e o caminho de destino correspondem ao método normal de instalação? Uma atualização inesperada entregue por um canal novo merece a mesma desconfiança que um signatário inesperado.

Não confunda um repositório público de código-fonte com um artefato de lançamento. Um repositório pode mostrar o histórico do código, enquanto a cadeia de lançamento compila um binário diferente. Da mesma forma, um binário assinado pode ser legítimo mesmo quando você não consegue reproduzir sua compilação. Esses são níveis de garantia diferentes. Declare qual nível você tem, em vez de fingir que um prova o outro.

A comparação de digest ajuda quando o editor fornece um checksum autenticado. Ela não ajuda quando você copia o checksum e o binário da mesma página não confiável. A comparação útil vem de um registro de versão controlado independentemente pelo editor, de um registro de gerenciador de pacotes confiável ou de uma fonte interna estabelecida anteriormente.

O acesso solicitado deve ser revisado junto com a atualização

Uma atualização do binário pode manter a mesma autoridade de assinatura e ainda merecer menos acesso do que a versão antiga tinha. O motivo da revisão não é apenas o medo de código malicioso. Um comportamento novo pode tornar uma permissão antiga inadequada.

Pergunte quais ações externas o processo executará depois da atualização. Um agente que antes lia metadados de issues pode agora criar pull requests. Um agente que usava um token descartável de teste pode agora executar comandos SSH em um host compartilhado. Um novo plug-in, uma mudança no formato de configuração ou um comando padrão diferente podem alterar o alcance prático do processo sem solicitar um novo entitlement ao sistema operacional.

A revisão do acesso solicitado deve cobrir o limite real das ações:

  • Quais hosts HTTP, escopos de conta e registros de credenciais o processo usará?
  • Quais destinos SSH e comandos remotos ele pode alcançar?
  • Qual diretório de trabalho, hooks do repositório, argumentos e variáveis de ambiente o iniciam?
  • Ele passou a receber entradas de uma fonte diferente, como um comentário em pull request ou um log de compilação?
  • Ele pode chamar outro executável local que não fazia parte da revisão anterior?

É aqui que uma aprovação ampla e permanente falha. Uma decisão como «permitir este agente» esconde a parte importante: permitir que ele faça o quê, com a credencial de quem e em resposta a qual entrada?

Para processos de agentes, a procedência das entradas merece a mesma atenção. Uma atualização que permite a um agente de programação agir sobre texto não confiável de issues pode transformar um acesso comum ao repositório em um caminho para prompt injection. A assinatura de código não examina as instruções recebidas pelo processo. Ela cobre apenas o programa que as interpreta.

Mantenha as telas de aprovação e os registros internos concretos. Informe a autoridade do processo, o destino, a classe da credencial e se a ação altera o estado remoto. Um operador não pode tomar uma decisão segura diante de um alerta que diz apenas «O agente solicita acesso».

Encerre a sessão antiga antes que o novo código possa agir

Veja cada chamada externa
O diário de atividades registra chamadas individuais, separando quem agiu de quem assinou o executável.

A regra mais clara é vincular a aprovação a um único processo em execução e encerrá-la quando esse processo terminar. Um binário substituto gera um novo processo, portanto recebe uma nova aprovação. Isso evita a tentativa frágil de decidir qual atualização de pacote é pequena o bastante para herdar uma concessão anterior.

Não permita que um processo se atualize no próprio lugar e continue usando a autorização obtida antes da substituição. Alguns atualizadores fazem exatamente isso: o processo antigo baixa um arquivo, grava um novo executável sobre o caminho antigo e depois inicia um auxiliar ou executa a si mesmo novamente. Se a camada de autorização verificar apenas um caminho ou um registro duradouro do cliente, o novo código continuará sob a decisão antiga.

Um registro prático de decisão pode ter esta aparência:

process path: /Users/dev/tools/agent/bin/agent
observed digest: 8a4b...e19c
identifier: dev.example.agent
TeamIdentifier: A1B2C3D4E5
parent: interactive shell in approved repository
requested actions: issue API read, test-host SSH command
approval scope: this process only
expires: process exit

Não trate o digest como uma entrada permanente de lista de permissões. Registre-o para saber que a próxima aprovação diz respeito a um código diferente. Quando o processo for reiniciado depois de uma atualização, compare a nova observação com a anterior e mostre ao operador as diferenças relevantes.

Uma reinicialização da mesma versão também pode exigir revisão quando o contexto de inicialização mudar. Um binário iniciado por um shell interativo em um repositório verificado não equivale ao mesmo binário iniciado automaticamente por um job de compilação com um ambiente mais amplo. O executável é uma parte do objeto. O contexto do processo o completa.

Inspecione as evidências do macOS antes de aprovar uma substituição

Você pode inspecionar um executável candidato com ferramentas integradas do macOS antes de permitir que ele faça uma chamada privilegiada. Execute os comandos contra o executável que será iniciado, não contra uma cópia com nome parecido na pasta Downloads nem contra um pacote de aplicativo externo que você presume que o contenha.

codesign -d -vvv /Users/dev/tools/agent/bin/agent 2>&1
spctl -a -t exec -vv /Users/dev/tools/agent/bin/agent
shasum -a 256 /Users/dev/tools/agent/bin/agent

A saída típica de codesign inclui campos parecidos com estes:

Identifier=dev.example.agent
Authority=Developer ID Application: Example Publisher (A1B2C3D4E5)
TeamIdentifier=A1B2C3D4E5
CDHash=8a4b9c0d...

spctl informa sua avaliação e costuma informar uma origem para softwares Developer ID aceitos. shasum imprime um digest SHA-256 completo seguido do caminho. Salve a saída relevante com o comprovante da versão. A redação exata varia entre versões do macOS, então compare os campos de identidade e a avaliação, não os espaços em branco ou a ordem dos campos.

Para um aplicativo empacotado, inspecione também o código interno. Um pacote externo assinado pode conter auxiliares, frameworks ou ferramentas de linha de comando. Se o agente iniciar um auxiliar diretamente, inspecione esse auxiliar diretamente. O arquivo que solicita acesso é o arquivo cuja identidade deve ser vinculada à decisão.

Uma verificação bem-sucedida de codesign não significa que um executável foi notarizado ou que é adequado para seu uso. Significa que a assinatura passou de acordo com as regras de verificação do comando. Vale preservar essa distinção nas notas de incidentes. Caso contrário, alguém pode ler mais tarde «assinatura válida» como «versão revisada e aprovada», que é uma afirmação muito maior.

Um caminho estável é uma maneira fácil de aprovar o código errado

Mantenha as credenciais fora dos agentes
O Sallyport mantém chaves de API e SSH em seu cofre criptografado, fora do processo do agente.

Considere um wrapper local em /Users/dev/bin/agent. Um desenvolvedor o aprova uma vez porque ele chama uma API de projeto somente para leitura. Mais tarde, o wrapper executa uma atualização automática, baixa um novo auxiliar e mantém o mesmo caminho. O componente de aprovação reconhece o caminho e concede ao novo auxiliar a permissão antiga.

Nada nessa sequência exige um invasor malicioso. A versão pode ser legítima. O problema é que o registro de aprovação diz «caminho igual ao caminho permitido», enquanto a decisão real foi tomada sobre um programa antigo, com comportamento mais limitado.

A falha piora quando o próprio wrapper é um script. Scripts de shell costumam chamar binários versionados por baixo de um symlink estável, ler configurações de um diretório gravável ou escolher um auxiliar a partir de PATH. Uma verificação de assinatura no wrapper informa pouco sobre o executável final se o wrapper puder redirecionar a execução depois da verificação.

Corrija a ordem das operações. Resolva o executável final. Inspecione sua assinatura e seu digest. Registre o processo pai e os argumentos. Depois autorize esse processo em execução. Se um inicializador puder substituir ou selecionar outro executável depois da aprovação, vincule o gateway de ações ao processo observado no momento da conexão e rejeite uma incompatibilidade.

A alternativa popular é herdar automaticamente a aprovação para qualquer atualização assinada pelo mesmo Team ID. As equipes escolhem isso porque os avisos incomodam os desenvolvedores e os certificados de lançamento geralmente continuam estáveis. Isso é errado para agentes privilegiados, porque trata uma credencial do editor como um cheque em branco para todos os comportamentos futuros. Reduza a fadiga causada por avisos com aprovações limitadas à sessão, acesso restrito e notificações claras de atualização, não tornando as atualizações invisíveis.

Mudanças de editor precisam de um registro explícito de migração

Uma mudança na autoridade de assinatura pode ser legítima. Empresas adquirem produtos, mudam para outra conta Developer ID ou substituem um processo antigo de distribuição. Trate esses eventos como migrações, não como atualizações de rotina.

Exija um registro explícito que informe a identidade anterior, a nova identidade, a versão em que a mudança ocorreu e as evidências usadas para aceitá-la. Boas evidências incluem um anúncio assinado no canal de lançamento estabelecido pelo editor, notas de versão correspondentes no repositório esperado e um pacote obtido pelo caminho normal de entrega. Um pop-up sem explicação não é evidência.

Uma mudança no Team ID deve ser negada por padrão até que alguém revise a migração. Um certificado alterado sob o mesmo Team ID pode seguir para uma nova aprovação depois da revisão normal de procedência e acesso. Um digest alterado com o mesmo certificado também exige uma nova aprovação porque é código novo, mesmo que todos os outros campos coincidam.

Não conceda uma exceção ampla como «aceitar todas as identidades futuras para este nome de aplicativo». Essa exceção transforma uma migração pontual em uma brecha permanente. Armazene a nova identidade somente depois que o revisor aceitar uma versão específica. A próxima mudança deve acionar a mesma revisão novamente.

Se sua equipe distribui agentes internos, publique a identidade de assinatura esperada, o digest da versão e o procedimento de atualização em um local que os operadores possam consultar sem depender do próprio agente. Um agente não pode atestar de forma confiável sua própria substituição enquanto essa substituição é o objeto em análise.

Um protocolo curto de aprovação é melhor que uma lista enorme de exceções

Evite listas amplas de permissões para atualizações
Três controles fixos substituem exceções permanentes: bloqueio do cofre, aprovação da sessão e chaves por chamada.

Você não precisa de um mecanismo de regras complicado para tornar previsíveis as decisões sobre atualizações. Precisa de um protocolo curto que seja aplicado sempre que o executável mudar.

  1. Pare o processo antigo e revogue sua sessão ativa.
  2. Resolva o executável final que fará a conexão ou agirá.
  3. Compare seu digest, identificador, autoridade de assinatura e Team ID com o comprovante da versão anterior.
  4. Verifique o canal de lançamento esperado e registre o motivo de qualquer mudança de identidade.
  5. Revise os destinos e as credenciais solicitados e, então, aprove a nova sessão do processo ou negue-a.

Esse protocolo separa uma atualização normal de manutenção de uma anomalia real. Um novo digest com a mesma autoridade e procedência normal de lançamento é um evento de revisão, não uma emergência. Uma autoridade desconhecida, um instalador inesperado e uma solicitação de credencial SSH de produção devem interromper a implementação até que alguém investigue.

A autorização de sessão do Sallyport pode tornar o limite do processo visível porque identifica um novo processo de agente antes de permitir sua execução, enquanto sua configuração de aprovação por chamada pode manter credenciais sensíveis sob uma decisão mais restrita. Isso não elimina a necessidade de inspecionar um agente atualizado, mas impede que uma execução antiga empreste silenciosamente sua aprovação a uma posterior.

Mantenha o registro curto o suficiente para que as pessoas o atualizem. As evidências úteis são o arquivo observado, seu signatário, sua origem, seu contexto de inicialização e as ações aprovadas. Se uma versão alterar qualquer um desses elementos, faça a pessoa responsável pelo risco ver a mudança antes que o agente aja.

Os registros de auditoria precisam distinguir o ator do editor

Um registro de auditoria que diga apenas «o agente usou a credencial» torna a análise posterior a um incidente desnecessariamente difícil. Registre qual processo fez a solicitação, qual autoridade de assinatura o macOS informou, qual sessão a autorizou e qual ação realmente aconteceu. A identidade do editor explica quem assinou o código. O registro do processo explica quem agiu.

Essa distinção importa quando uma execução do agente dá errado. Você precisa descobrir se uma nova versão mudou o comportamento, se um binário antigo foi executado de um local inesperado, se uma pessoa aprovou um pedido de acesso diferente do que imaginava ou se uma entrada não confiável orientou um processo que, de outro modo, era esperado. Um campo do editor sozinho não responde a essas perguntas.

Mantenha a integridade separada da legibilidade. Um registro que evidencie adulterações pode estabelecer se entradas anteriores foram alteradas. Ele não pode criar fatos ausentes depois do evento. Capture o digest do executável e o contexto da decisão no momento da aprovação, quando ainda é possível observá-los.

O Sallyport projeta seus diários de sessões e atividades a partir de um único registro de auditoria criptografado e encadeado por hash, e sp audit verify pode verificar essa cadeia offline sobre o texto cifrado. Use esse tipo de evidência para verificar o registro e associe-o a um comprovante da versão que explique por que o executável recebeu acesso em primeiro lugar.

A primeira mudança operacional que eu faria seria remover qualquer regra de aprovação que corresponda apenas a um caminho, nome de exibição ou editor. Substitua-a pela aprovação do processo atual, faça-a expirar quando o processo terminar e exija uma nova decisão depois de uma substituição do binário. Esse único limite captura o caminho de atualização que listas amplas de permissões costumam deixar passar.

FAQ

O mesmo Team ID é suficiente para confiar em um agente atualizado?

Não. Um Team ID ou certificado de desenvolvedor estável indica que o signatário continua associado ao novo arquivo. Isso não significa que o novo código mereça o acesso do processo antigo ou que a versão tenha chegado pelo canal esperado do editor.

Um agente precisa ser aprovado novamente depois de toda atualização?

Trate o novo executável como um novo objeto. Encerre a sessão do processo antigo, verifique a nova assinatura e a procedência, depois peça uma nova aprovação antes que ele possa usar credenciais ou agir externamente.

O que a assinatura de código do macOS realmente prova?

Uma assinatura de código associa a identidade de um signatário ao conteúdo de um arquivo e permite que o macOS detecte alterações feitas depois da assinatura. Ela não prova que a conta de lançamento do editor não foi comprometida, que o instalador veio do lugar certo ou que o acesso solicitado pelo programa continua adequado.

O que é um CDHash e devo armazená-lo?

CDHash identifica o diretório de código assinado usado pelo macOS e muda quando o código assinado relevante é alterado. Ele ajuda a detectar que um executável difere de uma compilação aprovada, mas não substitui a verificação da autoridade de assinatura e da origem da versão.

O que devo fazer se uma atualização do agente tiver um certificado de assinatura diferente?

Não transfira essa aprovação silenciosamente. Uma mudança na autoridade de assinatura exige uma revisão explícita, e uma mudança no Team ID normalmente deve bloquear a execução até que alguém confirme uma transferência documentada do editor ou uma migração planejada.

Quando devo verificar um binário de agente no macOS?

Inspecione o executável depois que ele chegar ao disco e antes da primeira ação privilegiada. O caminho de inicialização importa, porque um atualizador, uma ferramenta de arquivamento ou um script de substituição pode colocar outro arquivo no mesmo local mais tarde.

Como verifico a procedência de um executável de agente local?

Verifique o canal normal de lançamento do editor, o instalador ou arquivo assinado, qualquer digest publicado e as notas da versão que expliquem a mudança. Se não for possível estabelecer de onde o arquivo veio, uma assinatura válida sozinha é um motivo fraco para conceder acesso a credenciais de produção.

Uma aprovação de sessão pode sobreviver a uma atualização feita pelo próprio agente?

Ela deve expirar quando o processo terminar e não deve ser transferida para um binário substituto. Um processo em execução que se altera precisa de atenção especial, porque a identidade que recebeu a aprovação já não corresponde ao código que fará as chamadas seguintes.

É seguro autorizar um agente por caminho de arquivo?

Uma lista de permissões pode reduzir os avisos, mas falha quando corresponde apenas a um caminho, nome do pacote ou Team ID. Corresponda um binário específico observado na execução atual e exija uma nova decisão quando o hash, o requisito de assinatura, o contexto de inicialização ou o acesso solicitado mudar.

Como o Sallyport lida com a confiança depois de uma atualização do agente?

Sim, se o sistema mantiver o segredo fora do processo do agente e vincular a aprovação ao processo atual. O Sallyport faz isso por meio de um bloqueio do cofre e da autorização da sessão, mas o operador ainda precisa tratar um executável recém-alterado como uma nova execução que merece revisão.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov