Pular para o conteúdo
OmniRoute source

Socket.dev / supply-chain finding attestation (Português (Brasil))

§1 — Instalação da CA raiz para MITM (77484.js)

Seção intitulada “§1 — Instalação da CA raiz para MITM (77484.js)”

Arquivos-fonte:

  • src/mitm/cert/install.ts — funções públicas installCert() / uninstallCert() e installCertWindows/Mac/Linux específicas para cada plataforma.
  • src/mitm/systemCommands.ts — auxiliares compartilhados de execFile / spawn / PowerShell usados pelos caminhos de instalação.

Acionamento: o usuário clica em “Ativar proxy MITM” no painel local em /dashboard/cli-tools/mitm. A rota é restrita à interface de loopback — consulte a regra rígida nº 17 em CLAUDE.md e src/server/authz/routeGuard.ts::isLocalOnlyPath(). Um JWT vazado e exposto por meio de um túnel não pode acionar esse caminho de código.

Operações privilegiadas executadas (por plataforma):

SO Comando(s)
Windows certutil -addstore Root <cert> via UAC
macOS sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <cert>
Linux sudo cp <cert> <distro-trust-dir> + sudo update-ca-certificates (Debian) / sudo update-ca-trust (RHEL/SUSE)
Linux+Firefox/Chromium atualização do banco de dados NSS de cada perfil via certutil -d sql:<profile>

Esses são os mesmos comandos usados por mitmproxy, Charles Proxy, Fiddler e Caddy. O fato de eles existirem no OmniRoute está documentado em docs/security/STEALTH_GUIDE.md.

Mitigação da v3.8.6:

  • runElevatedPowerShell() não usa mais -EncodedCommand <base64utf16le>. O payload elevado é gravado em um arquivo temporário .ps1 para cada chamada (modo 0o600, dentro de um diretório privado mkdtempSync) e referenciado por meio de -File. O arquivo é desvinculado em finally. Isso remove a assinatura clássica de elevação via PowerShell usando base64, sinalizada pelo classificador de IA do Socket.dev.
  • installCertWindows contém um bloco inline SECURITY-AUDITOR-NOTE: que aponta para este documento.

Por que o mantemos: o proxy MITM é um recurso documentado usado por docs/security/STEALTH_GUIDE.md e docs/frameworks/MITM-PROXY.md. Removê-lo interromperia o conjunto de recursos da ponte de agentes.


§2 — Importação de credenciais do Zed (app/api/providers/zed/import/route.js)

Seção intitulada “§2 — Importação de credenciais do Zed (app/api/providers/zed/import/route.js)”

Arquivos-fonte:

  • src/app/api/providers/zed/discover/route.ts (novo na v3.8.6)
  • src/app/api/providers/zed/import/route.ts
  • src/lib/zed-oauth/keychain-reader.ts
  • src/lib/zed-oauth/credentialFingerprint.ts (novo na v3.8.6)

Acionamento: o usuário clica em “Importar do Zed” na página local de Provedores do painel. O endpoint é protegido por requireManagementAuth. O próprio editor Zed grava suas chaves de API dos provedores no chaveiro do sistema operacional, usando nomes de serviço documentados — consulte https://zed.dev/docs/ai/llm-providers.

Comportamento da v3.8.5 (o que o Socket.dev sinalizou):

POST /import descobria as credenciais e as salvava automaticamente no armazenamento SQLite local em uma única operação. Sem confirmação por conta, sem impressão digital, apenas “N tokens encontrados, todos importados”.

Mitigação da v3.8.6 — confirmação em 2 etapas:

  1. POST /api/providers/zed/discover retorna { candidates: [{ provider, service, account, fingerprint }] }. O token bruto nunca é transmitido. A impressão digital é sha256(service|account|token).slice(0,16).
  2. O painel exibe a lista de candidatos, o operador seleciona quais deseja importar e envia { confirmedAccounts: [{ service, account, fingerprint }] } para POST /api/providers/zed/import.
  3. O endpoint de importação relê o chaveiro no servidor e filtra por (service, account, fingerprint). Uma resposta de descoberta adulterada ou reproduzida não consegue induzir o endpoint de importação a salvar um token não relacionado — se o token ativo tiver sido alterado desde a descoberta, a impressão digital não corresponderá mais e a credencial será ignorada.

Uma variável de ambiente OMNIROUTE_ZED_IMPORT_LEGACY_ONE_STEP=true preserva o comportamento da v3.8.5 para operadores que ainda não atualizaram suas automações. Ela será removida na v3.9.

Por que mantemos isso: a importação do Zed é o caminho de integração mais amigável para usuários que já utilizam o Zed e desejam espelhar suas chaves de provedores no OmniRoute sem precisar colá-las novamente.


§3 — execFile / spawn / PowerShell elevado (21843.js)

Seção intitulada “§3 — execFile / spawn / PowerShell elevado (21843.js)”

Arquivos-fonte: src/mitm/systemCommands.ts.

Por que foi sinalizado: o chunk reexporta execFileWithPassword, runElevatedPowerShell e o auxiliar compartilhado quotePowerShell. O classificador de IA do Socket.dev os interpreta como um “kit de ferramentas genérico para execução no host + elevação de privilégios”. No OmniRoute, eles são usados somente pelo fluxo de instalação do certificado MITM (§1) e por execFileWithPassword para a execução de comandos sudo.

Mitigação da v3.8.6:

  • Refatoração de runElevatedPowerShell (consulte §1).
  • Um bloco SECURITY-AUDITOR-NOTE: embutido tanto em runElevatedPowerShell quanto em execFileWithPassword documenta os chamadores permitidos e a lista fixa de executáveis.
  • A chamada spawn() de execFileWithPassword contém um marcador nosemgrep com a lista permitida de executáveis que o auxiliar pode receber — não existe nenhum caminho da entrada do usuário até finalCommand/finalArgs.

§4 / §6 — Supervisor do serviço 9router (api/services/9router/{start,restart}/route.js)

Seção intitulada “§4 / §6 — Supervisor do serviço 9router (api/services/9router/{start,restart}/route.js)”

Arquivos-fonte:

  • src/app/api/services/9router/_lib.ts — fábrica do supervisor.
  • src/app/api/services/9router/{start,stop,restart,status,install,update,auto-start}/route.ts.
  • src/lib/services/ServiceSupervisor.ts — spawn genérico / sondagem de integridade / buffer de logs.

Acionamento: o usuário clica em “Instalar” / “Iniciar” na página de serviços integrados do painel local.

Proteções já existentes:

  • Todas as rotas /api/services/* são LOCAL_ONLY conforme src/server/authz/routeGuard.ts (regra rígida nº 17). A restrição a loopback ocorre antes de qualquer verificação de autenticação — um JWT vazado não consegue acessá-las.
  • O registro do 9router no banco de dados é criado com status='not_installed', auto_start=0 (consulte src/lib/db/migrations/071_services.sql:19). O serviço não é iniciado na primeira execução.
  • spawn() é chamado com o caminho do binário retornado por resolveSpawnArgs(apiKey, PORT) em src/lib/services/installers/ninerouter.ts, que consiste em uma lista fixa de binários compatíveis.
  • Stdout/stderr é armazenado em buffer na memória (limite de 5 MB, consulte _lib.ts) — nada é gravado em disco, a menos que o usuário habilite o registro de logs no painel.

Mitigação da v3.8.6: nenhuma alteração funcional. O perfil de compilação mínimo (OMNIROUTE_BUILD_PROFILE=minimal) substitui src/lib/services/installers/ninerouter.ts por um stub para usuários que desejam que os caminhos privilegiados sejam fisicamente removidos do pacote.

Por que mantemos isso: o 9router é um serviço complementar opcional e instalável localmente (pense em algo como um plugin do WordPress) — adesão estritamente voluntária.


§5 — Gravação de credenciais do OmniRoute Cloud Sync (api/keys/[id]/route.js)

Seção intitulada “§5 — Gravação de credenciais do OmniRoute Cloud Sync (api/keys/[id]/route.js)”

Arquivos-fonte:

  • src/lib/cloudSync.ts — syncToCloud() / updateLocalTokens().
  • src/app/api/keys/[id]/route.ts — invoca syncKeysToCloudIfEnabled().

Gatilho: isCloudEnabled() retorna true (definido pelo painel) e CLOUD_URL está configurada. Com ambos desativados, nenhuma chamada de rede de saída é feita ao endpoint do Cloud.

Comportamento da v3.8.5 (o bug que o Socket.dev detectou corretamente):

updateLocalTokens() sobrescrevia accessToken, refreshToken e providerSpecificData com os dados da resposta do Cloud quando cloudUpdatedAt > localUpdatedAt. Sem HMAC, sem assinatura, sem checksum. Uma CLOUD_URL configurada incorretamente ou hostil (ou um MITM no canal) poderia substituir silenciosamente os tokens OAuth do provedor.

Mitigação na v3.8.6:

  1. Verificação de HMAC: verifyCloudSignature(rawBody, sigHeader) verifica o cabeçalho X-Cloud-Sig (HMAC-SHA256(OMNIROUTE_CLOUD_SYNC_SECRET, rawBody)) antes de analisar o JSON. Se o segredo estiver definido, a assinatura será obrigatória. Caso contrário (modo legado), um aviso será registrado e a resposta será aceita — o segredo será obrigatório na v3.9.
  2. Ativação explícita de campos secretos: accessToken / refreshToken / providerSpecificData são sobrescritos somente quando OMNIROUTE_CLOUD_SYNC_SECRETS=true. O modo padrão sincroniza apenas metadados que não são credenciais (expiresAt, status, lastError*, rateLimitedUntil, updatedAt). Essa é uma alteração incompatível para usuários que dependiam da sincronização remota de tokens — eles devem ativá-la explicitamente.

Por que mantemos esse recurso: o Cloud Sync é a única forma de um tenant do OmniRoute Cloud centralizar as credenciais da equipe. A correção torna o modelo de ameaças transparente: “o servidor assina, o cliente verifica, o operador ativa explicitamente.”


Para usuários que precisam de um artefato compatível com o Socket, faça o build com:

Janela do terminal
OMNIROUTE_BUILD_PROFILE=minimal npm run build

O NormalModuleReplacementPlugin do webpack cria aliases de quatro módulos para stubs:

Módulo Stub
src/mitm/cert/install.ts src/mitm/cert/install.stub.ts
src/lib/zed-oauth/keychain-reader.ts src/lib/zed-oauth/keychain-reader.stub.ts
src/lib/cloudSync.ts src/lib/cloudSync.stub.ts
src/lib/services/installers/ninerouter.ts src/lib/services/installers/ninerouter.stub.ts

Cada stub exporta a mesma interface, mas todas as funções lançam um featureDisabledError(name) em tempo de execução. As rotas que dependem do módulo desativado retornam HTTP 503 com uma mensagem clara, em vez de ativar o caminho de código sensível.

O bundle resultante destina-se à publicação como omniroute-secure. Consulte docs/ops/PUBLISHING_SECURE.md para obter as instruções de publicação.


A longo prazo, pretendemos dividir o pacote npm em módulos que possam ser auditados separadamente. Consulte o marco da v4 no rastreador de issues do GitHub para acompanhar a issue correspondente.


Código-fonte do OmniRoute (a58000c7685f)

HagiCode

HagiCode é um ambiente de programação com agentes, fluxos estruturados, execução multiagente e visualizações Hero Dungeon.

Transforme ideias em software útil com um fluxo de trabalho com agentes mais inteligente, rápido e agradável.

Interface principal do HagiCode no tema claro
  • SmartFluxos estruturados transformam intenções em um caminho executável da ideia à entrega.
  • EfficientFluxos multiagente mantêm pesquisa, implementação e revisão em andamento simultaneamente.
  • FunO Hero Dungeon torna longas sessões de programação mais visuais e colaborativas.
Acessar HagiCode