# Secure Enclave e Touch ID para segredos de agentes de IA

Um agente de programação com IA deve conseguir solicitar uma ação sem jamais receber a credencial que a autoriza. Essa é a propriedade de segurança em torno da qual vale a pena construir o sistema. O Secure Enclave e o Touch ID podem impor parte dessa propriedade em um Mac, mas somente quando o segredo permanece atrás de uma barreira que o agente não consegue ler.

Um aviso do Mac dizendo que um agente pode acessar «GitHub» não é um projeto de segurança. Um token `ghp_...` copiado, um `AWS_SESSION_TOKEN` exportado ou uma chave privada SSH colada em uma chamada de ferramenta dá ao agente um poder duradouro que nenhum aviso posterior do Touch ID consegue retirar. A parte difícil não é criptografar a string. É recusar-se a entregá-la a um software que retransmite texto arbitrário.

Já vi esse erro de várias formas: um token colocado em `.env`, um auxiliar de credenciais que imprime uma senha, uma chave privada montada em um contêiner e, depois, um agente instruído a «usar todas as credenciais disponíveis». Cada escolha parece temporária. Cada uma transforma o segredo em parte do conjunto de trabalho do agente.

## O Secure Enclave não torna seguro entregar um token de acesso

O Secure Enclave pode proteger operações criptográficas, mas não consegue tornar inofensivo um token de acesso depois que um processo o lê. Essa distinção determina se o Touch ID protege um segredo de desenvolvedor ou apenas acrescenta um aviso cerimonial antes do vazamento.

A Apple descreve o Secure Enclave como um hardware isolado capaz de criar e usar chaves privadas sem expor o texto puro ao processador principal. Uma restrição documentada é importante: as chaves privadas do Secure Enclave são geradas ali, não podem importar chaves privadas existentes em texto puro e oferecem operações específicas de assinatura e acordo de chaves com P-256. Um token de API não é uma dessas chaves privadas. Normalmente é uma string opaca que um serviço remoto aceita de qualquer pessoa que a apresente. A documentação Apple Developer, «Protecting keys with the Secure Enclave», deixa claros tanto o isolamento quanto os limites.

Isso deixa três objetos diferentes que as pessoas costumam misturar:

- Uma chave privada do Secure Enclave é material de chave não exportável usado em operações criptográficas limitadas.
- Um item do Keychain são dados de aplicativo criptografados cujo acesso o macOS pode restringir.
- Uma credencial de acesso é um valor copiável que concede acesso onde quer que um serviço o aceite.

Tratá-los como sinônimos produz projetos ruins. Uma chave do Secure Enclave pode assinar um desafio sem se revelar. Um item do Keychain pode exigir a presença do usuário antes que o sistema devolva seus dados. Um token de acesso vira um segredo comum no momento em que um processo recebe seus bytes.

Por isso, «armazenamos o token no Keychain» não é uma resposta completa para um agente. Isso responde à questão do armazenamento em repouso. Não responde quem pode solicitar o token, qual processo o recebe, se esse processo pode passá-lo para um processo filho ou se pode escrevê-lo no stdout.

As orientações da Apple para o Keychain deixam clara a barreira. O Keychain Services pode exigir autenticação antes de devolver um item, e o Secure Enclave fornece apenas um resultado de aprovação ou reprovação para a verificação biométrica. Nem o app nem o sistema operacional recebem os dados da impressão digital. Essa é uma excelente proteção para o modelo biométrico. Ela não diz nada sobre o que um app autorizado fará com os bytes da senha devolvidos.

Não peça ao Touch ID para resolver um problema depois que você já entregou um segredo ao agente.

Um modelo melhor tem duas camadas. O processo do cofre pode recuperar ou usar uma credencial depois que o usuário passa pela barreira. O agente pode solicitar uma ação informando uma credencial e um destino, mas não pode ler ou substituir a credencial nem pedir que outra ferramenta a imprima. O processo do cofre executa a solicitação HTTP ou a autenticação SSH e retorna um resultado deliberadamente limitado.

Essa é uma interface mais estreita. Esse também é o objetivo.

## A barreira deve vir antes do stdout e das variáveis de ambiente

Os segredos de desenvolvimento escapam pelo encanamento comum muito antes de um invasor precisar derrotar a criptografia. Variáveis de ambiente, herança para processos filhos, rastreamento do shell, registros de depuração, relatórios de falhas, respostas de ferramentas e saída de terminal copiada transformam um segredo protegido em um segredo portátil.

Sou direto sobre isso porque o modo de falha é previsível: se um agente pode executar `printenv`, ler `.env`, chamar um auxiliar de credenciais ou obter uma chave de API como resultado de uma ferramenta MCP, ele tem a credencial. O armazenamento original ter usado Keychain, um gerenciador de senhas ou um arquivo criptografado já não muda a ameaça.

Considere este fluxo comum:

```text
Agent -> runs a shell command -> credential helper reads Keychain
      -> helper prints token -> shell captures stdout
      -> agent receives token -> token appears in context or logs
```

O aviso do Keychain pode ter funcionado exatamente como planejado. O sistema autenticou o usuário do Mac. Depois, o auxiliar converteu um item protegido em texto, que o agente recebeu pelo mesmo canal usado para erros do compilador e resultados de testes.

É nesse momento que o projeto falha.

Um caminho seguro para a credencial é materialmente diferente:

```text
Agent -> requests "POST api.example.com/releases" using credential "release-bot"
      -> gateway asks for authorization if required
      -> gateway obtains or uses credential internally
      -> gateway sends HTTPS request with Authorization header
      -> agent receives status, selected headers, and response body
```

O agente recebe o resultado da ação autenticada, não o cabeçalho de autorização. Parece uma pequena escolha de API. É a linha que separa a execução delegada da distribuição de segredos.

A mesma regra vale para SSH. Não passe ao agente um caminho para `~/.ssh/id_ed25519`, um `SSH_AUTH_SOCK` capaz de assinar desafios arbitrários sem uma barreira visível nem um comando que possa extrair uma chave de um armazenamento seguro. Deixe um auxiliar com escopo limitado estabelecer a conexão SSH e executar o comando solicitado. Retorne stdout, stderr, o status de saída e informações sobre a identidade do host. Mantenha a chave privada fora da árvore de processos do agente.

Existe um custo. Algumas ferramentas de desenvolvimento presumem que podem ler as credenciais diretamente, e uma abordagem com gateway significa criar adaptadores, APIs de ferramentas mais estreitas e lidar ocasionalmente com fluxos de autenticação incomuns. Prefiro pagar esse custo de engenharia uma vez a fazer a rotação de um token de produção depois que ele aparecer na transcrição de um agente.

Não confunda um disco criptografado com um caminho de execução controlado.

## O Touch ID prova presença, não intenção

O Touch ID pode provar que uma pessoa aprovou uma barreira em determinado momento. Ele não prova que ela entendeu o próximo comando do agente, que o comando corresponde à intenção do repositório ou que o destino é seguro.

O framework LocalAuthentication da Apple expõe deliberadamente um resultado limitado ao app: o framework coordena a ação com o Secure Enclave e retorna sucesso ou falha. O app que chama fornece o texto do motivo e escolhe uma política de autenticação. Essa separação está correta. O sistema não deve fingir que consegue interpretar a intenção do aplicativo a partir de um evento biométrico.

No trabalho com agentes, trate o Touch ID como uma barreira sobre uma capacidade, não como aprovação de um texto. Um cartão que diga «Permitir que este agente use credenciais de produção» fornece pouca informação ao usuário. Um cartão que identifique o processo assinado, o host de destino, o rótulo da credencial e se a aprovação vale para uma chamada ou uma execução dá ao usuário algo concreto para avaliar.

Prefiro três momentos de autorização distintos:

1. Desbloquear o cofre. Enquanto o cofre estiver bloqueado, toda ação baseada em segredos falha. Não deve existir um caminho de «usar uma alternativa desprotegida».
2. Aprovar um novo processo do agente durante sua execução. A aprovação deve identificar a autoridade de assinatura do código, não apenas um nome de processo mutável como `node` ou `python`.
3. Exigir a presença do usuário a cada uso de credenciais com alcance irreversível, como um token de implantação em produção, uma função de proprietário na nuvem ou uma chave SSH capaz de alterar uma frota.

A aprovação por sessão é o padrão correto para agentes de programação. Um novo processo é uma barreira importante: uma nova inicialização pode usar outro binário, outro espaço de trabalho, outras variáveis de ambiente herdadas ou outra configuração MCP. A aprovação permanente silencia ações posteriores justamente quando sua origem ficou mais difícil de verificar.

A aprovação por chamada deve continuar sendo rara, mas precisa ser rigorosa quando a credencial pode causar um dano amplo. Um token que apenas abre um rastreador de problemas em modo de leitura não merece uma impressão digital a cada `GET`. Uma credencial SSH capaz de executar `kubectl apply` em produção merece. Isso cria interrupções, e essa interrupção é intencional.

A alternativa popular é um arquivo de políticas grande: aprovar comandos que correspondam a esta expressão regular, permitir domínios nesta lista de permissões e rejeitar argumentos que contenham determinadas palavras. Essa abordagem parece escalável porque substitui avisos por automação. Ela também cria uma segunda linguagem de programação que precisa modelar aspas do shell, redirecionamentos, wrappers, links simbólicos, `curl --config`, payloads codificados, expansão de comandos remotos e toda nova ferramenta instalada por um agente.

Eu não colocaria autoridade de produção atrás de uma gramática que ninguém audita depois de sexta-feira.

Use uma pequena sequência de decisões: bloqueado ou desbloqueado, esta execução foi aprovada ou não, esta credencial precisa de uma nova aprovação ou não. Esses controles têm um significado claro quando começa a revisão de um incidente.

## Os controles de acesso do Keychain têm detalhes perigosos

Um item biométrico do Keychain só é útil quando você escolhe deliberadamente a restrição de acesso, entende seu comportamento alternativo e impede que o processo autorizado se torne um distribuidor de segredos.

A Apple documenta `SecAccessControlCreateWithFlags` para associar requisitos de disponibilidade e autorização a um item do Keychain. Para um segredo local de desenvolvedor que não deve migrar por backup ou pelo iCloud Keychain, `kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly` costuma ser a classe de armazenamento sensata. Ela exige um código do dispositivo e torna o item indisponível se o código for removido; o sufixo `ThisDeviceOnly` também impede sua transferência para outro dispositivo.

Para um segredo que deve exigir uma verificação biométrica, use uma flag de controle de acesso em vez de tentar colocar um aviso ao redor de uma consulta comum ao Keychain. Este trecho simplificado em Swift armazena uma senha genérica que somente o conjunto biométrico registrado atualmente pode liberar:

```swift
import Security

let access = SecAccessControlCreateWithFlags(
    kCFAllocatorDefault,
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
    .biometryCurrentSet,
    nil
)!

let item: [CFString: Any] = [
    kSecClass: kSecClassGenericPassword,
    kSecAttrService: "com.example.agent-gateway",
    kSecAttrAccount: "release-bot",
    kSecAttrAccessControl: access,
    kSecValueData: Data(token.utf8)
]

let status = SecItemAdd(item as CFDictionary, nil)
precondition(status == errSecSuccess)
```

`biometryCurrentSet` é mais rigorosa que `biometryAny`. Ela vincula o acesso às impressões digitais ou aos dados faciais registrados atualmente, de modo que uma alteração no conjunto biométrico registrado invalida o item protegido. `biometryAny` aceita qualquer dado biométrico registrado e não oferece o mesmo sinal de alteração no cadastro. A Apple lista as duas flags em `SecAccessControlCreateFlags`; escolha a primeira quando uma nova impressão digital deve exigir um novo provisionamento deliberado.

A recuperação precisa de um contexto de autenticação e de um aviso de operação que descreva a ação em termos humanos:

```swift
import LocalAuthentication
import Security

let context = LAContext()
context.localizedReason = "Use release-bot for the requested deployment action"

let query: [CFString: Any] = [
    kSecClass: kSecClassGenericPassword,
    kSecAttrService: "com.example.agent-gateway",
    kSecAttrAccount: "release-bot",
    kSecReturnData: true,
    kSecMatchLimit: kSecMatchLimitOne,
    kSecUseAuthenticationContext: context,
    kSecUseOperationPrompt: "Authorize credential use"
]

var result: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &result)
```

O código está incompleto de propósito em um aspecto: ele não diz o que fazer com `result`. Um app convencional poderia convertê-lo em `Data`, criar um cabeçalho `Authorization` e continuar. Um gateway de agente precisa garantir que esses dados permaneçam dentro do processo que realiza a chamada autenticada. Não os retorne na resposta MCP. Não os coloque em um arquivo temporário. Não os registre quando a solicitação falhar.

Tenha cuidado com as janelas de reutilização. O exemplo da Apple mostra que a validação do Touch ID pode reutilizar um evento recente de desbloqueio do dispositivo durante um período configurado, de até cinco minutos. Essa conveniência ajuda apps comuns a evitar avisos repetidos. Em um ponto de controle de agente, ela pode apagar o momento de aprovação deliberada que você pretendia exigir. Não use uma janela de tolerância para credenciais que exigem aprovação a cada uso, a menos que tenha decidido conscientemente aceitá-la e documentado a decisão.

Há outro limite que vale mencionar. Os dados biométricos podem falhar, ficar indisponíveis ou ser bloqueados após tentativas malsucedidas. A Apple oferece políticas que permitem fallback para o código do dispositivo e políticas que exigem biometria. Decida qual delas sua alegação de segurança exige. Se você disser «Touch ID em toda implantação de produção», aceitar silenciosamente um caminho alternativo não relacionado muda essa alegação e também deve mudar o texto exibido na interface.

## Siga uma instrução maliciosa até o ponto em que ela vence

Um agente não precisa de uma exploração dramática para abusar de uma credencial. Ele precisa de uma instrução plausível, uma capacidade ampla e um canal de saída que devolva mais do que o usuário pretendia.

Imagine um agente de programação ajudando com um pull request. Ele lê um documento do repositório adicionado por um invasor. O documento diz que a verificação da versão exige a execução de um script auxiliar. O script usa a sessão existente da CLI de nuvem do desenvolvedor, lista credenciais de implantação e envia uma solicitação codificada a um endpoint externo. O agente tem permissão para executar comandos shell e herdou `AWS_PROFILE`, `GH_TOKEN` ou acesso a um agente SSH.

A primeira falha aconteceu antes da execução do script: o desenvolvedor deu ao agente credenciais disponíveis no ambiente. A segunda ocorreu quando o executor de ferramentas permitiu que o agente escolhesse destinos de rede arbitrários. A terceira aconteceu quando os registros e a saída dos comandos devolveram material de autenticação ou detalhes da sessão ao contexto do agente.

O Touch ID no login não salvaria esse projeto. A pessoa pode ter se autenticado uma hora antes e depois se afastado. Um item do Keychain protegido apenas por «dispositivo desbloqueado» pode ficar disponível para um processo que o usuário nunca pretendeu autorizar para essa tarefa. A própria Apple alerta que o acesso com o dispositivo desbloqueado pode não ser restritivo o bastante para todos os casos de uso.

Agora mude a arquitetura. O agente solicita uma ação com estes campos:

```json
{
  "channel": "http",
  "credential": "release-bot",
  "method": "POST",
  "url": "https://api.example.com/releases",
  "body": {"branch": "feature/fix-ci"}
}
```

O gateway resolve `release-bot` internamente. Ele compara o destino solicitado com a ação que executará, pede autorização se a credencial exigir, injeta o cabeçalho por conta própria e registra a ação. O agente recebe o status HTTP e uma resposta redigida. Nunca vê o valor do cabeçalho.

O documento do repositório ainda pode convencer o agente a solicitar uma implantação ruim. Por isso a revisão do destino e da ação é importante. Mas o documento não pode instruir o agente a exfiltrar um token que ele nunca possuiu. Também não pode reutilizar o token contra outro serviço depois que a chamada aprovada terminar.

Isso reduz de forma significativa o raio de impacto, mas não é mágica. Um agente comprometido que tem aprovação para implantar ainda pode implantar algo prejudicial. O sistema limitou o roubo de credenciais e tornou a ação atribuível; não resolveu a revisão maliciosa de código nem substituiu o julgamento humano.

Ao revisar configurações de agentes, procuro o primeiro ponto em que uma instrução pode virar uma string secreta. Normalmente é ali que a correção deve acontecer.

## Identificadores de capacidade são mais seguros que strings secretas

Um agente deve solicitar uma capacidade nomeada com parâmetros estruturados de ação, enquanto um processo local confiável resolve essa capacidade para uma credencial e executa o efeito colateral.

A palavra «capacidade» é usada de forma vaga. Aqui, ela significa uma referência útil apenas dentro do gateway, como `release-bot`, `staging-ssh` ou `billing-read`. Não é um alias de token que o agente possa trocar pelo token. Não é uma variável de modelo expandida em um valor de ambiente. É um seletor passado a um processo que mantém acesso exclusivo à credencial.

Essa escolha impõe disciplina à interface da ferramenta. As ferramentas HTTP devem aceitar o método, a URL, os cabeçalhos que o agente pode fornecer com segurança e o corpo. A injeção da credencial deve acontecer depois da validação, dentro do gateway. As ferramentas SSH devem aceitar um host, um usuário, um comando e uma identidade de credencial selecionada, e então chamar um auxiliar que seja dono do caminho de autenticação. Elas não devem retornar um caminho `IdentityFile` nem oferecer uma operação genérica de «ler segredo».

É aqui que uma interface sem surpresas vence. Um shell geral que herda todas as credenciais do desenvolvedor oferece suporte a mais ferramentas no primeiro dia. Também torna quase impossível responder qual agente usou qual conta em qual solicitação de saída. Uma interface HTTP e SSH limitada tem menos alcance inicial, mas preserva os fatos necessários para tomar uma decisão de segurança.

O Sallyport segue esse formato: o agente usa o shim stdio integrado `sp mcp` para solicitar ações HTTP ou SSH, enquanto o app mantém as credenciais de API e SSH dentro do cofre criptografado e realiza a ação por conta própria. O agente recebe o resultado, não as credenciais em texto puro.

A limitação é honesta. Uma ferramenta que conhece apenas HTTP e SSH não cobre automaticamente todos os apps de desktop, clientes de banco de dados, registros de pacotes ou binários locais do ambiente de um desenvolvedor. Adicionar um canal deve exigir o projeto do seu modelo de ações, do comportamento de redação, das regras de autorização e dos campos de auditoria. Um botão amplo de «executar qualquer coisa com meu login» é mais fácil de lançar e mais difícil de defender.

Use rótulos explícitos de credenciais que revelem seu alcance pretendido. `prod-deployer` é melhor que `token-4`. `github-readonly-org` é melhor que `github`. O rótulo passa a fazer parte da decisão humana e do registro de auditoria, então a ambiguidade vira um problema operacional, não uma preferência de nomenclatura.

Mantenha o formato da solicitação estreito o bastante para que o gateway possa exibi-lo sem interpretação. Um revisor entende `POST https://api.example.com/releases`. Ele não consegue inferir com segurança o efeito de um bloco Base64 canalizado por um wrapper de shell.

## Um registro de auditoria deve descrever a ação sem copiar o segredo

Um gateway de credenciais precisa de dois registros: a execução do agente que obteve autoridade e cada efeito colateral que ele tentou produzir. Um único fluxo de logs do terminal não consegue fornecer os dois sem perder contexto ou vazar material sensível.

Registre a execução quando um novo processo de agente solicitar acesso. Capture a identidade do processo disponível para o gateway, sua autoridade de assinatura de código, o horário de início, a decisão de aprovação e o estado de revogação. Se o usuário revogar a execução, solicitações posteriores desse processo devem falhar mesmo que ele continue ativo.

Registre cada ação separadamente. Para HTTP, mantenha o rótulo da credencial, o método, o destino, o status, o tempo e um resumo cuidadosamente escolhido do corpo. Para SSH, mantenha o rótulo da credencial, o host, o usuário remoto, o comando, o código de saída e o tempo. Não registre cabeçalhos `Authorization`, valores de acesso, bytes de chaves privadas, corpos completos de solicitações que contenham dados de clientes nem saída irrestrita de comandos.

Logs que contêm segredos viram outro cofre, com controles de acesso piores.

A evidência de adulteração importa porque um incidente com um agente costuma começar com uma linha do tempo contestada: «O agente chamou este endpoint?», «A sessão foi aprovada?», «Alguém editou o histórico local?». Um registro de eventos encadeado por hash oferece um objeto concreto para verificação posterior. O verificador deve funcionar sem precisar descriptografar cada evento; caso contrário, a pessoa que verifica a integridade precisa receber os dados sensíveis que o registro deveria proteger.

O Sallyport projeta seus diários de Sessões e Atividades a partir de um único registro de auditoria criptografado, encadeado por hash e sem possibilidade de alteração pelo processo que escreve, e `sp audit verify` verifica a cadeia offline sem uma chave do cofre. Essa propriedade é útil porque a revisão de integridade não deve exigir acesso aos segredos do desenvolvedor.

Uma cadeia de hashes não impede que uma máquina comprometida tente uma ação ruim. Ela dificulta a reescrita silenciosa da sequência registrada e oferece uma sequência consistente para a investigação. Não a venda como prevenção.

O Apple Platform Security e a documentação Apple Developer Security são leituras úteis porque separam proteções de hardware, controles do sistema e responsabilidades do aplicativo. Essa separação é exatamente o que a segurança de agentes exige. O hardware seguro pode controlar o acesso, mas o aplicativo ainda escolhe o que envia pela rede e o que grava no disco.

## O acesso à produção precisa de menos caminhos, não de suposições mais inteligentes

A implantação mais segura para agentes de programação com IA começa com um pequeno conjunto de credenciais nomeadas, destinos conhecidos, identidade de sessão visível e uma classe de ação irreversível que exige uma nova aprovação. O acesso amplo disponível no ambiente é um convite para descobrir seu modelo de ameaças durante uma interrupção.

Use esta revisão antes de permitir que um agente toque em uma credencial:

1. Confirme que o agente não consegue ler o segredo por meio de variáveis de ambiente, arquivos, um auxiliar de credenciais, saída de ferramentas ou um processo filho.
2. Confirme que o processo confiável realiza a solicitação HTTP ou a autenticação SSH e injeta a credencial depois que o agente envia parâmetros estruturados.
3. Configure o bloqueio do cofre para negar toda ação baseada em segredos. Teste com o app bloqueado, não apenas com a tela do Mac bloqueada.
4. Exija uma nova aprovação de sessão quando um novo processo do agente for iniciado e faça com que a aprovação identifique sua autoridade de assinatura.
5. Marque credenciais com alcance de implantação, administração, destruição ou SSH amplo para autorização a cada uso.

Teste os casos desagradáveis. Adicione um segredo falso, como `canary-agent-secret-9f31`, a uma credencial que não seja de produção. Peça ao agente para inspecionar o repositório, executar testes e informar a saída das ferramentas. Depois procure a string exata na transcrição, no histórico do terminal, nos diretórios temporários, nos logs, no ambiente dos processos filhos e nos registros de auditoria. Se ela aparecer em qualquer lugar fora do processo do cofre, o projeto entregou ao agente um caminho para o segredo.

Faça o mesmo com a revogação. Aprove uma execução, faça uma solicitação inofensiva, revogue a execução enquanto o processo continua aberto e tente fazer a mesma solicitação novamente. A segunda solicitação deve falhar antes de chegar ao serviço remoto. Um controle de revogação que só entra em vigor depois de uma reinicialização é burocracia, não contenção.

Não use um aviso biométrico como decoração ao redor da exportação de uma credencial. Coloque o aviso na barreira em que o usuário autoriza um processo ou uma ação específica e mantenha a credencial do lado protegido. É assim que o Secure Enclave e o Touch ID se tornam controles úteis para agentes de programação com IA, em vez de uma história tranquilizadora sobre armazenamento.
