08/Documentation
Segurança de um durable agent
O que um durable agent pode e não pode fazer, as regras de confiança do socket e do token, o que o Collie faz com o texto de um durable agent e o que o log de auditoria mantém
Experimental. O protocolo de rede, o SDK e esta página podem mudar, ou o recurso pode ser removido, em uma versão secundária posterior. Durable agents explica o que decide sua permanência.
Um durable agent é código que você executa ou faz deploy, e o Collie trata suas palavras como texto não confiável. Esta página descreve o que um durable agent pode acessar, o que impede que outros o acessem, o que o Collie faz com seu texto e o que o log de auditoria mantém. Segurança cobre o Collie como um todo.
O que um durable agent pode e não pode fazer
Um durable agent pergunta, e um dispositivo pareado decide. Um durable agent recebe o que você responde e envia para ele, além das requisições da rede. O Collie não dá a ele nenhuma forma de acessar seus terminais.
| um durable agent pode | um durable agent não pode |
|---|---|
| Fazer uma pergunta: um sim ou não, uma escolha, uma linha de texto ou um formulário curto | Responder à própria pergunta através do Collie |
| Listar starters e colocar até quatro botões próprios na barra | Digitar nos seus terminais ou mostrar uma tela |
Inserir texto, código e links https:// em uma conversa | Mostrar HTML bruto, uma imagem ou um link que não seja um endereço web |
| Escolher as palavras da sua própria notificação push, dentro dos limites | Enviar mais notificações push do que a proteção permite |
Apenas o toque de uma pessoa responde a uma pergunta. A rota de resposta é executada para um dispositivo pareado protegido pelo controle de escrita, e nada na ponte a chama para um durable agent, um hook ou a saída de um modelo. No telefone, a opção "Sempre permitir" exige um segundo toque. Um durable agent que a oferece possui a concessão que exige mais cuidado, pois uma única resposta de uma ferramenta hostil liberaria todas as chamadas posteriores sem perguntar.
O durable agent, e não o Collie, aplica o que uma ação aprovada faz. Um botão do durable agent executa com os privilégios do durable agent, e o Collie apenas envia o toque.
Um durable agent não pode inundar sua tela de bloqueio. O Collie decide cada pergunta uma única vez, indexada pelo durable agent e pela chamada de ferramenta, e envia uma notificação push no máximo uma vez. Ele permite 3 notificações push por conversa a cada minuto, 10 por host a cada minuto e 30 por host a cada hora. A notificação que seria a 31ª se torna uma única notificação de resumo, e o host não envia mais nenhuma até uma hora depois dela. Um card é sempre exibido.
Atenção. O mesmo usuário pode responder a uma pergunta em um socket. Um socket bloqueia outros usuários, não um processo do seu próprio usuário, e isso inclui uma ferramenta executada pelo seu agente. A verificação de descendentes é a própria defesa do durable agent, e o Collie não consegue saber se um durable agent a executa.
Com a verificação, um durable agent recusa answer, send, abort, action, rename, close, reopen e starter vindos de si mesmo, de qualquer processo iniciado por ele e de qualquer originador que não possa distinguir deles. A recusa é 403 caller-refused, e as leituras continuam abertas. A verificação precisa do Bun no Linux, onde o SDK lê o originador de um socket. A tabela mostra o que ela aplica onde o durable agent é executado:
| onde o durable agent executa | o que a verificação de descendentes aplica |
|---|---|
| Bun no Linux | Executa por padrão. O SDK lê o originador de cada conexão e recusa uma ação vinda do durable agent, de seus descendentes ou de um originador que não consiga identificar, com 403 caller-refused |
| Bun em outros ambientes, como macOS | Não pode executar. openCollie para na inicialização com um erro, a menos que o durable agent passe callerCheck: "off". Com off, qualquer processo do seu usuário pode responder |
| Node | Não pode executar. O durable agent inicia e escreve uma única linha de aviso. Qualquer processo do seu usuário pode responder |
Isole as ferramentas do agente em uma sandbox sem acesso ao socket, trate o card como um aviso em vez de um controle de acesso, ou execute o durable agent no Bun. callerCheck: "off" é a escolha do próprio durable agent de executar sem a verificação.
O transporte via socket
Um socket privado bloqueia qualquer outro usuário, e seu único controle de acesso é o caminho.
ls -ld /run/user/1000 /run/user/1000/desk /run/user/1000/desk/app.sockO socket não carrega nenhum token e nenhum cabeçalho Authorization. O Collie conecta apenas quando todo o caminho é privado, e executa esta verificação antes de cada conexão, a partir de / para baixo, com lstat, para não seguir nenhum link:
| parte | o que o Collie exige | o que o motivo diz |
|---|---|---|
| Cada parte do caminho, incluindo o socket | Não um link simbólico, mesmo que aponte para um bom local | socket-not-private: <path> is a symlink |
| A própria pasta do socket | Uma pasta real, sua, com modo exatamente 0700 | the socket's folder <path> has mode 0755, not 0700, ou belongs to user <a>, not to <b>, ou <path> is not a directory |
| Cada pasta acima dela | Uma pasta real na qual grupo e outros não podem escrever. Uma pasta com o sticky bit, como /tmp, é permitida lá, nunca como a própria pasta do socket. Seu proprietário não é verificado, porque um serviço com um /tmp privado mostra as pastas do root como o usuário 65534 | <path> has mode 0775, so group or others can write to it |
| O socket | Um socket, seu, sem permissão para grupo ou outros | the path is not a socket, the socket belongs to user <a>, not to <b>, the socket has mode 0666, not 0600 |
| Uma plataforma sem IDs de usuário | Falha fechada: o Collie nunca disca | this platform shows no file owner |
| Windows | Apenas o transporte HTTPS está disponível: collie durable attach --socket recusa antes de escrever | a private socket needs Unix user ids; on Windows use --url <https://...> --token-env VAR |
Um caminho com falha fica inacessível imediatamente, sem carência. collie doctor indica a mesma verificação em sua linha durable-socket e oferece a correção. Um caminho vazio lê no socket at <path>, o que não é uma falha de privacidade.
Um agente durável construído com o SDK cria a pasta do socket com modo 0700 quando ela não existe. Ele se recusa a iniciar em uma pasta existente com outro modo. Ele define o socket para o modo 0600 e remove um arquivo de socket inativo antes de escutar.
O transporte via socket é para Linux e macOS. O Windows não tem transporte via socket, portanto use o transporte via token lá.
O transporte por token
Uma URL e um token alcançam um agente durável em outro host, e o token é o controle de acesso completo.
openssl rand -hex 32| regra | valor |
|---|---|
| Token | 32 a 4096 bytes após remoção de espaços nas extremidades, ASCII imprimível sem espaços |
| URL | https://, ou http://127.0.0.1:<port> ou http://localhost:<port> para um agente durável nesta máquina. No máximo 2048 bytes. Sem nome de usuário, senha, query ou fragmento |
| Certificado | Verificado como qualquer cliente verifica. O Collie não tem opção para ignorá-lo |
| Redirecionamentos | O Collie não segue nenhum, portanto o token nunca chega a outro host |
Quem possui o token age como seu telefone. Pode ler todas as conversas, responder a cada pergunta, enviar texto, interromper um turno, renomear ou fechar e executar um starter. Uma conexão TLS da internet não tem chamador para verificar, então a verificação de descendente não existe aqui. Um agente durável acessado dessa forma deve oferecer apenas Permitir e Negar, nunca permitir sempre.
O host vê o texto. O TLS termina no host, então ele vê cada requisição, incluindo o token no cabeçalho, e as conversas ficam em seu armazenamento.
O Collie mantém o token em texto puro em dois lugares. sources.json o mantém para uma entrada, e um backup ou sincronização da pasta de configuração o carrega. O Collie mantém esse arquivo no modo 0600, restringe permissões mais amplas na inicialização com uma linha em seu log, e collie doctor mostra uma linha sources vermelha para um que o grupo ou outros possam ler. A forma somente durável o mantém em .env ou config.toml, e um arquivo que o armazena deve ter o modo 0600. O Collie nunca imprime o token. collie durable list diz (token set), collie doctor diz set, <n> bytes, e nenhum erro ou linha de log carrega o valor. attach o lê da variável que --token-env indica, portanto ele não está em nenhuma linha de comando.
O token não expira. Para rotacioná-lo, forneça o novo token ao agente durável antes de reiniciar o Collie, caso contrário o telefone informará que o agente durável o recusou. Um agente durável pode aceitar um segundo token enquanto uma rotação ocorre: o exemplo do Cloudflare aceita COLLIE_TOKEN e, enquanto ele estiver definido, COLLIE_TOKEN_NEXT (ADR 0103). As etapas estão em Tokens.
Esta é uma chamada de saída que o Collie faz para a URL que você configurou, e ela é recusada ao não anexar nada. Cada requisição carrega Authorization: Bearer <token>, a versão de protocolo, o ETag da última leitura e, para um toque, o corpo do que você respondeu ou enviou. Uma leitura é um GET sem corpo.
Cada sondagem via HTTPS é uma requisição que seu host pode faturar, e uma resposta "nada mudou" conta também. Sem nenhum telefone aberto, a sondagem ociosa roda a cada 10 s, então o Collie pergunta 8.640 vezes por dia, e a cada 2 s enquanto um telefone monitora. Um agente durável que está inativo ou recusa o token é consultado no máximo uma vez a cada 10 s, e essas requisições também são faturadas. Use um plano pago para um agente durável que o Collie sonda o dia todo.
O que o Collie faz com o texto de um agente durável
O Collie limpa todas as strings de um agente durável antes que qualquer outra coisa as leia e as renderiza como texto.
Um agente durável deve enviar strings dentro dos limites. O Collie não presume que ele fez isso. Cada string passa por três etapas:
- Controles são removidos. O Collie remove controles C0, DEL e controles C1. Campos com várias linhas mantêm a quebra de linha e a tabulação: o texto de um item, a saída e o resumo de uma chamada de ferramenta e o motivo de uma pergunta.
- Caracteres invisíveis e de direção são removidos. O Collie remove as marcas de direção U+200E, U+200F e U+061C, as substituições e isolamentos U+202A a U+202E e U+2066 a U+2069, os caracteres de largura zero U+200B a U+200D, o juntador de palavras U+2060, a marca de ordem de bytes U+FEFF e os caracteres de tag U+E0000 a U+E007F, que podem carregar uma frase invisível inteira.
- A string é cortada. O Collie corta a string no limite de bytes em um caractere inteiro e termina com
….
Uma pergunta cujo título ou motivo mudou na limpeza exibe uma marcação "Texto encurtado" em seu cartão. Uma opção ou um botão de faixa sem palavras restantes é descartado, de modo que um botão nunca fica em branco. Um campo sem nenhuma é nomeado pelo seu id.
| texto | limite |
|---|---|
| Um título de um workspace, uma aba, uma conversa ou uma pergunta | 256 bytes |
| Uma opção, um campo ou um rótulo inicial | 128 bytes |
| Um rótulo de botão de faixa | 16 caracteres |
| O motivo de uma pergunta | 2048 bytes |
| A saída de uma chamada de ferramenta | 16384 bytes |
| O texto de uma mensagem ou de uma resposta | 65536 bytes |
O texto de um item markdown ou code | 32768 bytes |
| Texto que você envia para um agente durável | 1 a 32768 bytes, recusado antes de sair |
| Uma resposta de um agente durável | 16 KiB para hello, 4 MiB para um snapshot |
Ids nunca são limpos ou cortados. Um id tem de 1 a 128 bytes sem caractere de controle, sem espaço em branco e sem /, ? ou #, caso contrário o objeto que o contém é descartado.
O Collie renderiza o texto como texto. Um item markdown exibe títulos, listas, ênfases, trechos de código e links, e HTML puro nunca é renderizado: uma tag aparece com seus próprios caracteres. Um link dentro de um item markdown abre apenas um endereço web. Um item link precisa de um endereço https:// com um host, sem nome de usuário ou senha, sem espaços, caracteres de controle ou invisíveis, e com no máximo 2048 caracteres. Caso contrário, o Collie descarta o item e grava uma linha no log para cada conversa. Imagens e arquivos não são itens.
O que é registrado no log
O Collie grava cada escrita feita por um telefone para um durable agent em <state-dir>/audit.log, modo 0600.
Cada linha contém o nome do durable agent como session, o dispositivo pareado e o evento:
| evento | quando | o que a linha mantém |
|---|---|---|
answer | Um toque respondeu a uma pergunta | O id da requisição, a pergunta e sua revisão, o id da opção ou o tipo de resposta (optionIds, text ou values) e o resultado. Nunca as palavras que você digitou |
send | Você enviou ou direcionou texto | O id da requisição, o turno ou pergunta indicada, steer, o resultado e o texto como uma prévia de 120 caracteres |
abort | Você interrompeu um turno | O id da requisição, o turno ou pergunta indicada e o resultado |
action | Você tocou em um botão do cinto | O id da requisição, o id da ação, o turno e o resultado |
starter.start | Você tocou em um inicializador | O id do inicializador, o id da requisição e o resultado |
durable.reopen | Você reabriu uma conversa fechada | O id da conversa |
space.rename | Você renomeou um espaço de trabalho | O id do espaço e o novo nome |
Fechar e renomear uma conversa ou uma aba usa os eventos normais, pane.close, pane.rename e tab.rename. COLLIE_AUDIT_CONTENT=none oculta todas as strings nos detalhes, exceto alguns campos específicos como o id da requisição; assim, a prévia de um send é removida junto. O log mostra o que aconteceu depois do fato. Ele não impede nada.
O Collie também mantém um comprovante para cada resposta, envio, parada, toque de botão e inicializador, sem o texto digitado. Onde o Collie mantém os dados de um durable agent indica por quanto tempo.