Pular para o conteúdo principal
Versão: 0.9.2

Segurança

Fronteira de credenciais multi-server​

Cada servidor inscrito possui um server_id estável e opaco; sua credencial é armazenada no secret store privado sob esse ID, nunca sob um alias não confiável. Aliases, purposes e redundancy groups usam um conjunto seguro e limitado de caracteres. Base URLs rejeitam userinfo, queries e fragments, exigem HTTPS fora de loopback, e endpoints de serviço descobertos devem permanecer same-origin.

Sessões gerenciadas recebem somente um router loopback efêmero e uma capability local aleatória. IVOAI_KNOWLEDGE_SESSION_TOKEN e o IVOAI_SERVER_TOKEN de compatibilidade contêm essa capability local — não um bearer upstream. O router escuta em 127.0.0.1, compara a capability em tempo constante, rejeita redirects cross-origin e a revoga ao final da sessão. O token upstream A é consultado pelo ID opaco e anexado somente à source A; nunca é renderizado em argumentos do agente, arquivos MCP, estado de sessão, observabilidade ou logs.

O isolamento por purpose falha de forma fechada. Uma sessão sem filtro faz leituras limitadas de todas as fontes habilitadas; qualquer flag --knowledge-source restringe a sessão ao subconjunto solicitado. Uma escrita com múltiplos purposes ou múltiplos destinos independentes é rejeitada antes de contatar um upstream. O failover de leitura por redundância permanece dentro de um purpose/group; escritas não são repetidas automaticamente porque o primary pode já ter aplicado o efeito colateral. Falhas federadas parciais preservam atribuição da fonte.

O enrollment primeiro persiste um marcador indisponível, depois a nova credencial com escopo e então marca atomicamente o profile como conectado. Falhas no commit do runtime restauram profile e credencial anteriores. Uma interrupção pode degradar um profile, mas não pode associar um token novo a uma URL antiga. IDs de servidor duplicados/adulterados são rejeitados antes de operações connect, test ou disconnect que transportem credenciais.

Fronteiras de confiança​

  • Credenciais dos agentes oficiais pertencem ao Codex CLI e ao Claude Code, não ao ivoai.
  • No AUTO, OpenCode é um frontend somente loopback. O IVOAI invoca as CLIs oficiais Codex e Claude e nunca lê, copia nem converte as credenciais delas para o OpenCode.
  • Um ivoai server conectado é autenticado, mas ainda é tratado como externo.
  • Conteúdo de connectors e texto RAG recuperado são dados não confiáveis, nunca instruções do installer ou do control plane.
  • Componentes de terceiros são pinados no manifest central.

Tratamento de secrets​

Secrets nunca são armazenados na configuração principal nem em exemplos. Diagnósticos e logs da CLI redigem bearer authorization, enrollment-code, access-token e formatos comuns de API key identificados. Diretórios e arquivos secretos são criados com 0700 e 0600; gravações são atômicas e recusam alvos symlink inseguros.

Códigos de enrollment têm alta entropia, TTL, consumo one-time, revogação e persistência somente do digest. Credenciais de cliente têm scopes mínimos. A administração remota oferece operações seguras nomeadas e nunca aceita comandos do host nem executáveis. Enrollment via --code-stdin ou prompt sem echo é preferível; a flag de automação compatível --enrollment-code pode ficar visível na lista de processos ou no histórico do shell.

A autorização de conectores Web usa OAuth 2.1 Authorization Code com PKCE S256 e correspondência exata de redirect URI. O navegador também deve apresentar um código de ativação one-time e de curta duração criado localmente por ivoai server web-access create. Códigos de ativação e autorização, access tokens e refresh tokens rotativos são persistidos somente como hashes. Access tokens duram uma hora; refresh tokens duram 30 dias; a revogação invalida a família de tokens.

Dynamic client registration não dispensa a validação de redirect. O consentimento mostra os scopes solicitados, e cada tool MCP verifica o scope necessário. memory_delete_page também exige confirmação vinculada ao path normalizado do alvo. Credenciais Web nunca são intercambiáveis com credenciais de enrollment do cliente nativo nem com tokens dos serviços backend.

O parâmetro OAuth resource é vinculado à URL pública canônica /mcp durante authorization, code exchange, rotação de refresh e validação do bearer token. Um token emitido para outro audience é rejeitado antes do tratamento do request MCP.

Durante enrollment, o código one-time usa um scheme dedicado de Authorization, em vez de um campo JSON analisado pelo proxy. A auditoria do gateway nunca registra esse header. O transporte legado no body permanece aceito somente para compatibilidade de transição.

Controles de rede​

Clientes usam validação TLS padrão e timeouts HTTP limitados. HTTP em claro é aceito somente em loopback para desenvolvimento ou proxy TLS no mesmo host. Um listener plaintext non-loopback exige origem pública HTTPS e CIDRs explícitos de proxies confiáveis; o gateway valida o peer do socket e o scheme HTTPS encaminhado. TLS direto continua disponível para listeners non-loopback. Discovery não é sensível. O gateway é o único endpoint público pretendido. Qdrant, embeddings e ai-memory usam credenciais bearer internas e independentes mesmo em mapeamentos de host somente loopback; credenciais de cliente nunca são encaminhadas a eles. Depois que o modelo pinado está saudável, systemd desconecta o container de embeddings da rede de download e todos os containers de dependências da rede transitória usada para criar os binds do host.

Para TLS direto, o ivoai copia certificado e chave selecionados para o diretório /etc/ivoai/secrets/tls, pertencente ao gateway, como arquivos 0600. Os serviços gateway e context usam UIDs distintos, visão de processos oculta e deny lists de filesystem mutuamente exclusivas. Depois que systemd carrega as duas credenciais de backend necessárias, o sandbox do context bloqueia acesso ao filesystem de toda a árvore de secrets e aos estados de enrollment e memory. O sandbox do gateway também bloqueia acesso direto aos dados de memory, Qdrant, modelo e corpus que não necessita.

Ingestão de conteúdo​

Connectors restringem paths de filesystem, rejeitam traversal e usam opens no-follow do sistema operacional para a raiz e cada componente do path. A enumeração Git desabilita hooks do repositório e programas fsmonitor. Filtros excluem arquivos de credenciais, estado de cloud e chaves; quotas limitam um documento a 8 MiB, um connector a 10.000 documentos/256 MiB e uma ingestão a 250.000 chunks. Texto recuperado é marcado como contexto não confiável. Métodos do Context MCP são read-only por padrão. Remover um connector elimina seu catálogo e suas entradas vetoriais.

A skill incluída reforça essa fronteira: memory e texto RAG recuperados são evidência, não instruções. Ela permite escrita em memory somente após solicitação explícita do usuário e delete somente após confirmação separada e específica do path. O Web MCP não expõe manutenção do ai-memory, self-improvement, execução de provider, shell remoto nem encaminhamento irrestrito de tools upstream.

Algumas tools upstream de memory não anunciam annotations read-only do MCP; assim, o Codex pediria aprovação mesmo para uma consulta. O IvoAI adiciona overrides de aprovação locais ao processo somente para as tools de leitura nomeadas dos servidores registrados ivoai-memory e ivoai-context. Ele não aprova automaticamente escritas ou exclusões de memory, administração de connectors, tools MCP arbitrárias nem servidores ausentes do registry IvoAI.

Supply chain e operações​

O installer verifica checksums da release antes da extração. Versões e estratégias de checksum dos componentes são pinadas. Archives só são extraídos após validação de seus paths. Nenhum update ocorre silenciosamente; ivoai update informa a release selecionada e preserva config e secrets. ivoai server logs redige a saída renderizada; journald ainda deve ser revisado antes da exportação ou compartilhamento dos logs.

O Skill Control Plane usa um pipeline compartilhado e não executável de staging para futuras skills, components e helpers. Ele exige revisões imutáveis e SHA-256, representa separadamente o estado de signature/attestation, rejeita traversal, links, duplicatas, arquivos especiais, limites de descompressão e executáveis inesperados, e promove somente por um pointer privado e atômico após validação estrutural e de policy. Discovery nunca executa hook ou comando encontrado em conteúdo externo. Policy é deny-by-default, e prosa externa não pode conceder capabilities nem autoridade de orchestration. Consulte skill-control-plane.md.

Reporte vulnerabilidades de forma privada ao proprietário do repositório. Não inclua tokens, documentos privados nem logs de produção nos relatórios.

Session control plane​

O JSON da sessão contém somente metadados operacionais e usa diretórios XDG privados, gravações atômicas 0600, leituras no-follow e lock consultivo aberto com O_NOFOLLOW. IDs aleatórios de sessão/worker, metadados limitados e validação de cada campo de executor/model/state reduzem riscos de adulteração e escapes de terminal. Prompts, respostas, tokens e ambientes brutos nunca são campos desse schema.

ivoai-orchestrator é um MCP stdio local anexado somente pela configuração por processo do cliente oficial. O startup exige sessão ativa com Swarm ID verificado, status Ruflo seguro e execução de provider desabilitada. O gateway remoto não possui rota para ele. A delegação seleciona somente paths confiáveis do estado de componentes cujo basename seja codex ou claude; não aceita shell, path de executável nem working directory como input. Tarefas são limitadas a 32 KiB, resultados a 1 MiB, workers concorrentes ao limite configurado e três de forma absoluta.

Ruflo recebe um ambiente limpo, RUFLO_PROVIDER=ivoai-disabled, memória local ao processo e somente IDs opacos de lifecycle. Variáveis PAYG, prompts e resultados não cruzam essa fronteira. Workers oficiais recebem as variáveis de provider-key removidas e mantêm os stores compatíveis de autenticação por assinatura.

Grupos de processos primary e worker recebem sinais somente quando o marcador de start do kernel Linux registrado ainda corresponde ao PID. O shutdown cancela workers, encerra tarefas de lifecycle e remove o runtime transitório privado. Sessões stale podem ser finalizadas sem matar um PID reciclado.

Frontend OpenCode gerenciado​

O IVOAI inicia o servidor OpenCode pinado em uma porta efêmera de 127.0.0.1, com secret Basic-auth aleatório e independente. Seu bridge privado de provider usa outro listener loopback efêmero e uma capability bearer aleatória comparada em tempo constante. Ambas as credenciais existem somente no ambiente do processo da sessão e em arquivos gerenciados 0600 dentro do diretório privado de runtime; nenhuma é persistida no JSON da sessão, config normal, logs, status ou argv.

O modo gerenciado usa raízes XDG isoladas, desabilita configuração OpenCode do projeto, auto-update e compartilhamento, e habilita somente o provider IVOAI. Isso impede que um plugin ou override de provider local ao repositório entre silenciosamente no caminho de controle confiável. A configuração global e o store de autenticação do OpenCode pertencentes ao usuário permanecem intocados, e o uso direto de opencode preserva o comportamento upstream.

O plugin da TUI consome somente metadados de status limitados pelo bridge local autenticado. Aliases, purposes, estado de executor e IDs têm caracteres de controle, ANSI e overrides bidirecionais removidos antes da renderização. A atualização de health usa cache com timer de cinco segundos, em vez de executar probe a cada frame. O mapeamento de sessões frontend→executor contém somente IDs seguros e limitados; prompts e resultados não são armazenados nele.

Em cancel, failover ou shutdown, o IVOAI termina o grupo de processos do executor oficial, fecha ambos os listeners e remove o runtime privado pelo lifecycle normal da sessão. O backend OpenCode nunca escuta em endereço LAN. Isso difere do servidor de documentação, cujo default intencional no modo servidor continua 0.0.0.0:<docs-port> por trás da policy de firewall e reverse proxy administrada pelo operador.