Proteção da Cadeia de Fornecimento

Um agente de programação autónomo instala pacotes constantemente — a estruturação de um projeto puxa centenas de dependências sem que um humano alguma vez leia um nome, quanto mais um registo de alterações. Isso torna o registo de pacotes o canal mais amplo para a entrada de código hostil no sandbox: um nome typosquatted, um lançamento recém-comprometido ou um script postinstall malicioso é executado com todas as permissões do agente no instante em que npm install termina. O Bromure Agentic Coding trata cada obtenção de pacote como entrada não fiável e aplica-lhe uma política por máquina no anfitrião, antes de um único byte chegar à VM.

Este capítulo explica o que é intercetado, cada verificação do pipeline, o que acontece quando uma verificação dispara e como ler os resultados na Linha do tempo de segurança. A política da cadeia de fornecimento é definida por máquina (um espaço de trabalho, no editor de definições). A referência de definições campo a campo para o painel encontra-se em definições da Cadeia de fornecimento.

Porque é que as instalações de pacotes são a superfície de ataque

O sandbox já contém o agente: não pode tocar no seu Mac, e as suas credenciais são engodos (ver Credenciais). O que o sandbox não consegue fazer por si só é avaliar a proveniência do código que o agente puxa. Os ataques à cadeia de fornecimento exploram exatamente essa lacuna:

  • Comprometimento de lançamentos recentes. A conta de um mantenedor é comprometida e é publicada uma versão maliciosa. Estas versões são normalmente detetadas e retiradas em poucas horas a dias — razão pela qual o portão de idade recusa versões mais recentes do que um limite.
  • Versões com vulnerabilidades conhecidas. O agente resolve uma dependência para uma versão com um aviso publicado. A verificação OSV apanha estas situações.
  • Malware, typosquats e scripts de instalação fraudulentos. Pacotes concebidos para serem maliciosos desde o início. Os fornecedores socket.dev e Depi sinalizam ou filtram estes, e a remoção de scripts de instalação elimina desde logo o vetor de execução mais comum.

A imposição é feita no lado do anfitrião por conceção. O proxy aplica a política à resposta antes de o agente a ver, pelo que nada em execução dentro da VM — incluindo um agente totalmente comprometido — pode afrouxar as regras. Os ficheiros .npmrc e pip.conf internos da VM só podem restringir ainda mais aquilo que o proxy já serviu, nunca ampliá-lo. As chaves de API dos serviços de reputação (socket.dev, Depi) são mantidas apenas no anfitrião e nunca são exportadas para a VM.

Como funciona a interceção

Cada pedido de rede que a VM faz passa pelo proxy MITM do lado do anfitrião (ver Conceitos). O proxy reconhece pedidos aos principais registos de pacotes e classifica cada um:

  • Metadados — a listagem de versões de um pacote (um packument npm, a API JSON ou o índice /simple/ do PyPI, uma entrada de índice esparso do Cargo, e por aí adiante). O portão de idade opera aqui, reescrevendo a listagem.
  • Artefacto — o ficheiro descarregável de uma versão específica: um .tgz npm, uma wheel ou sdist Python, um .crate, .gem, .nupkg ou o .zip de um módulo Go. As consultas OSV, as verificações socket.dev, a remoção de scripts e os bloqueios rígidos acontecem todos no momento da obtenção do artefacto.
  • Passagem direta — tudo o resto nesses anfitriões (pesquisa, autenticação). Intocado.

Cada obtenção de pacote é classificada e registada na Linha do tempo de segurança, seja qual for a política; as verificações em si só são executadas para as camadas que ativar. Não há nada para instalar nem configurar dentro da VM.

Nota: Os pacotes já presentes na cache local do npm ou do pip nunca chegam à rede, pelo que nada é verificado — ou registado — para eles. Uma Linha do tempo silenciosa durante uma instalação pode simplesmente significar que tudo veio da cache.

Veredictos: permitir, reescrever, bloquear, reter

As camadas da cadeia de fornecimento são comutadores individuais de ligar/desligar, cada um com uma ação fixa — não existe um modo global de bloquear/avisar/permitir para este painel. (O botão de rádio de três vias registar/perguntar/bloquear que talvez conheça da Injeção de prompt, e os modos de imposição das Salvaguardas, são sistemas separados.) Cada obtenção termina num de quatro resultados:

ResultadoO que aconteceMarcador visível
PermitidoA resposta passa intocada.Linha verde verificado / transferido na Linha do tempo de segurança.
ReescritoO proxy modificou a resposta: versões demasiado recentes removidas dos metadados, ou scripts de instalação removidos de um tarball. O gestor de pacotes prossegue normalmente.Cabeçalho de resposta X-Bromure-Rewritten: supply-chain; linha azul na Linha do tempo.
BloqueadoO descarregamento é recusado com uma resposta HTTP 451 ("Indisponível por Razões Legais").Cabeçalho X-Bromure-Block: supply-chain; linha vermelha na Linha do tempo.
Retido para consentimentoO descarregamento faz uma pausa enquanto o Bromure lhe pergunta — para passagens diretas fixadas por lockfile, para pacotes que nenhuma fonte de reputação ativada conseguiu avaliar e para pacotes sinalizados pelo OSV ou pelo socket.dev (ver Confiar num pacote bloqueado). Negar converte a retenção num bloqueio 451.Um alerta de consentimento do sistema; a decisão é registada.

Um bloqueio 451 transporta um corpo em texto simples que começa por Bromure Supply-Chain Security blocked this request: seguido da razão exata, por exemplo:

Bromure Supply-Chain Security blocked this request: npm package [email protected]
published 4 hours ago — policy requires 2 days minimum

O npm, o pip, o cargo e os outros gestores de pacotes imprimem esse corpo textualmente na sua saída de erro, pelo que tanto o agente como você veem exatamente o motivo pelo qual uma instalação falhou — e o agente consegue muitas vezes contorná-lo por conta própria (por exemplo, fixando uma versão mais antiga). O estado 451 foi escolhido deliberadamente para que os bloqueios da cadeia de fornecimento sejam distinguíveis num relance dos 403 que as Salvaguardas usam.

Cobertura por ecossistema

O proxy interceta oito ecossistemas de pacotes. Nem todas as verificações suportam todos os ecossistemas:

EcossistemaAnfitriões intercetadosPortão de idadeOSVsocket.devDepiRemoção de scripts
npmregistry.npmjs.org, *.npmjs.orgSimSimSimSimSim
PyPIpypi.org, files.pythonhosted.orgSimSimSim——
Cargocrates.io, static.crates.io, index.crates.ioSimSimNão——
RubyGemsrubygems.orgSimSimSim——
Maven Centralrepo1.maven.org, repo.maven.apache.org, search.maven.orgNãoSimSim——
NuGetapi.nuget.org, *.nuget.orgNãoSimSim——
Módulos Goproxy.golang.orgNãoSimSim——
Packagistrepo.packagist.org, packagist.orgSimSimSim——

Duas lacunas que vale a pena conhecer:

  • Portão de idade — Maven, NuGet, Go. Estes três ecossistemas não transportam carimbos de data/hora de publicação por versão nas suas respostas de metadados padrão, pelo que os seus metadados passam sem filtragem e a rede de segurança do artefacto não tem dados sobre os quais atuar. O portão de idade efetivamente não os bloqueia hoje; npm, PyPI, Cargo, RubyGems e Packagist estão totalmente cobertos.
  • socket.dev — Cargo. O socket.dev não tem suporte para Cargo. Com a filtragem socket.dev ativada, cada artefacto crates.io não produz veredicto e, portanto, dispara o pedido de consentimento de pacote não verificado (ver Comportamento offline e degradado). Se a sua máquina faz muito trabalho em Rust, ou responde aos pedidos ou escolhe um fornecedor diferente.

O portão de idade

O portão de idade recusa versões de pacotes mais recentes do que um número configurável de dias, partindo do princípio de que um lançamento recém-publicado é o que tem maior probabilidade de ser um pacote acabado de comprometer — as versões maliciosas são normalmente reportadas e retiradas rapidamente, e esperar por essa janela quase não tem custo para o desenvolvimento normal. É a única camada ativada por predefinição, com um mínimo de 2 dias.

O painel Cadeia de fornecimento do editor da máquina Web app, mostrando o grupo Portão de idade com Recusar pacotes mais recentes do que o limite assinalado e Idade mínima definida como 2 dias, e o grupo Verificação de vulnerabilidades OSV desassinalado por baixo

Funciona através de dois mecanismos cooperantes:

  • Reescrita de metadados. O proxy remove as versões demasiado recentes da listagem de versões do registo e reaponta latest e outras dist-tags para a versão sobrevivente mais recente. As referências flutuantes — pkg@latest, intervalos semver — nunca são, portanto, bloqueadas rigidamente: o gestor de pacotes resolve silenciosamente para a versão mais recente com idade suficiente para passar. Do ponto de vista do agente, as versões mais recentes do que o limite simplesmente ainda não existem.
  • Rede de segurança na obtenção do artefacto. Cada tempo de publicação por versão que o proxy vê nos metadados é guardado em cache na memória (até 50 000 entradas). Se o agente pedir depois diretamente uma versão fixada e demasiado recente, a obtenção é bloqueada com um 451 que indica a idade real do pacote e o mínimo exigido. Para o pip — cujo índice HTML PEP 503 predefinido não transporta carimbos de data/hora — o Bromure realiza uma consulta a pedido de https://pypi.org/pypi/<pkg>/<version>/json para obter o tempo de publicação.

Para o configurar, abra o painel Cadeia de fornecimento da máquina e use o grupo Portão de idade:

  1. Ative Recusar pacotes mais recentes do que o limite.
  2. Defina Idade mínima: com o seletor (0–90 dias).
  3. Se um pacote específico tiver de estar instalável imediatamente — por exemplo, a sua própria equipa publica-o — adicione-o em Pacotes isentos com o botão Adicionar entrada. As entradas usam o formato de lista de permissões: npm:axios restringe a isenção a um ecossistema, um simples axios corresponde ao nome do pacote em todos os ecossistemas. A correspondência não distingue maiúsculas de minúsculas.

Dica: Os pedidos de metadados do npm são silenciosamente atualizados para o packument completo para que o portão possa ver os tempos de publicação — não precisa de fazer nada para o formato de metadados abreviado do npm.

Verificação de vulnerabilidades OSV

A verificação OSV consulta o ecossistema, o pacote e a versão de cada artefacto descarregado em api.osv.dev — a base de dados gratuita Open Source Vulnerabilities, que agrega a GitHub Advisory Database, os avisos do PyPI, a base de dados de vulnerabilidades do Go, o RubySec e outros. Se algum aviso para essa versão exata estiver no nível de gravidade escolhido ou acima dele, o descarregamento é bloqueado com um 451. Cobre todos os oito ecossistemas e não requer chave de API.

A gravidade é retirada da etiqueta GHSA quando o aviso tem uma; caso contrário, o Bromure calcula a pontuação base CVSS v3 a partir da string de vetor do aviso.

No grupo Verificação de vulnerabilidades OSV:

  1. Ative Consultar pacotes em api.osv.dev (gratuito, sem chave necessária).
  2. Escolha Bloquear na gravidade: — Baixa e superior, Média e superior, Alta e superior ou Apenas crítica.

A verificação está desativada por predefinição, e o limiar de gravidade tem como predefinição Alta e superior — como o próprio painel indica, um CVE de baixa gravidade num subpacote transitivo não deve interromper um fluxo de trabalho. As consultas são executadas apenas em descarregamentos de artefactos (não em obtenções de metadados), os resultados são guardados em cache na memória durante a execução da aplicação, no máximo 16 consultas são executadas em paralelo, e os erros de rede transitórios são repetidos até 5 vezes com recuo. Se o OSV não puder ser contactado de todo, o pacote é retido para o seu consentimento em vez de ser silenciosamente permitido — ver Comportamento offline e degradado.

Filtragem de pacotes: socket.dev e Depi

O grupo Filtragem de pacotes seleciona um fornecedor de reputação através de um botão de rádio mutuamente exclusivo: Nenhum, socket.dev ou Depi. Os dois fornecedores funcionam de formas fundamentalmente diferentes — o socket.dev é uma consulta prévia que o proxy consulta antes de deixar passar uma obtenção; o Depi substitui completamente o registo npm. Só um pode estar ativo de cada vez por conceção (executar ambos filtraria duplamente cada instalação), e selecionar Nenhum desativa ambos, mantendo quaisquer chaves armazenadas. Independentemente do fornecedor que escolher, as outras camadas deste capítulo — portão de idade, OSV, remoção de scripts — continuam a aplicar-se por cima.

A predefinição é Nenhum. Os espaços de trabalho criados antes de o botão de rádio existir que já tenham uma chave socket.dev são automaticamente inferidos como socket.dev.

socket.dev

O socket.dev é um serviço comercial de reputação de pacotes. Com socket.dev selecionado e uma chave de API introduzida, o proxy verifica cada descarregamento de artefacto na API de problemas do socket.dev antes de o servir. Suporta npm, PyPI, Go, Maven, RubyGems, NuGet e Packagist — mas não Cargo (ver Cobertura por ecossistema).

Você traz a sua própria chave: clique em Obter uma chave de API ao lado do campo Chave de API: (abre socket.dev/dashboard/settings/api-tokens), crie um token e cole-o no campo seguro. Ambos os comutadores de bloqueio permanecem desativados até uma chave ser introduzida, e uma chave vazia desativa o socket.dev por completo, independentemente dos comutadores. A chave é armazenada no lado do anfitrião no profile.json do espaço de trabalho e nunca entra na VM; todas as consultas têm origem no seu Mac.

Estão disponíveis dois bloqueios independentes:

  • Bloquear pacotes comprometidos (scripts de instalação fraudulentos, sinalizados como malware, typosquats, telemetria suspeita) — dispara nos problemas de risco da cadeia de fornecimento com forma de ataque do socket.dev. Sinais definitivos de malware (malware, malware conhecido, malware detetado por GPT, pacotes troll, chaves SSH comprometidas) bloqueiam em qualquer gravidade. Sinais com forma de ataque mais ruidosos — código ofuscado, strings suspeitas, scripts de instalação, typosquatting, acesso a shell, uso invulgar de HTTPS — bloqueiam apenas quando o socket.dev os classifica como alto ou crítico, para que um pacote com um postinstall benigno não seja apanhado. Sinais puros de qualidade e de atributos (novo autor, leituras de variáveis de ambiente, acesso à rede, telemetria) deliberadamente nunca bloqueiam.
  • Bloquear pacotes com CVEs conhecidos — dispara no balde de vulnerabilidades do socket.dev no nível do seletor Limiar de bloqueio de CVE: ou acima dele (os mesmos quatro níveis do OSV; predefinição Alta e superior).

Ambos os bloqueios estão desativados por predefinição. Os resultados são guardados em cache durante a execução da aplicação, no máximo 16 chamadas são executadas em paralelo, e as falhas transitórias são repetidas 5 vezes com recuo. Os erros de autenticação são escritos no registo da aplicação com o estado HTTP e uma pré-visualização do corpo da resposta.

Nota: Se ativar em conjunto o OSV e o bloqueio de CVE do socket.dev, ambos verificarão cada artefacto — isso é permitido (são camadas diferentes), apenas redundante para a cobertura de CVE. Muitos utilizadores emparelham antes o bloqueio de pacotes comprometidos do socket.dev com a verificação OSV gratuita.

Depi

O Depi é um registo npm seguro pronto a usar da Lupin & Holmes (landh.tech) que serve pacotes previamente avaliados. Em vez de consultar pacotes, o Bromure reencaminha cada pedido ao registo npm — metadados, tarballs, auditoria, tudo o que seja endereçado a registry.npmjs.org ou *.npmjs.org — para o registo de filtragem compatível com npm do Depi em depi-npm-proxy.landh.tech:443, anexando a sua chave como um cabeçalho Authorization: Bearer e removendo qualquer cabeçalho Authorization que o convidado tenha enviado. O Depi reescreve os URLs dos tarballs nos seus packuments para apontarem para si próprio, pelo que essas obtenções subsequentes também recebem a chave injetada no lado do anfitrião.

Para o ativar, selecione Depi no botão de rádio e cole a sua chave no campo seguro Chave de API: (Obter uma chave de API abre landh.tech). Enquanto o campo estiver vazio, um aviso laranja diz Introduza uma chave de API — o Depi permanece desativado sem uma. Cada pedido reencaminhado é escrito no registo da aplicação:

[depi] GET registry.npmjs.org/… → https://depi-npm-proxy.landh.tech

O tratamento de erros é explícito e não silencioso:

  • 401 (chave rejeitada). O Bromure substitui por um erro claro em texto simples que o npm imprime ("Bromure: the Depi registry rejected the configured API key…", com o cabeçalho X-Bromure-Block: depi-auth), regista-o e emite um alerta gráfico único por combinação de espaço de trabalho e chave: "Depi rejected your API key". As sessões SSH/TUI sem interface não recebem o alerta gráfico; dependem da linha de registo e do erro npm reescrito.
  • 403 (pacote bloqueado pelo Depi, ou chave não autorizada para ele). Registado e passado sem alterações, pelo que o npm reporta o texto de recusa do próprio Depi.

O Depi afeta apenas o npm — os outros sete ecossistemas ficam intocados por ele. O Depi substitui o socket.dev no botão de rádio, não a sua política local: o portão de idade, a verificação OSV e a remoção de scripts continuam a ser executados sobre aquilo que o Depi serve.

Remoção de scripts de instalação

Os hooks preinstall, install, postinstall e prepare do npm executam código arbitrário no momento da instalação e são o cavalo de batalha do malware npm no mundo real. Com Remover preinstall / install / postinstall / prepare dos tarballs npm em tempo real ativado (no grupo Scripts de instalação), o proxy reescreve cada tarball npm em trânsito: descomprime o .tgz, localiza o package/package.json de nível superior, remove essas quatro chaves de script, recalcula a soma de verificação do cabeçalho tar e volta a comprimir com gzip.

Como os bytes do tarball mudam, o proxy também limpa dist.integrity e dist.shasum dos metadados de registo do pacote, para que o npm calcule ele próprio o hash a partir do tarball com scripts removidos e a sua verificação continue a passar para instalações não fixadas. Cada remoção é registada ("scripts de instalação removidos de" o pacote e a versão, mostrado a laranja); os tarballs que foram inspecionados e considerados limpos são marcados apenas com o cabeçalho X-Bromure-Rewritten: supply-chain. Em qualquer falha de análise, o tarball original passa intocado — esta camada falha de forma aberta, porque nunca deve inutilizar uma instalação bem formada.

Alguns pacotes precisam genuinamente de scripts de instalação — compiladores de bindings nativos como o better-sqlite3 ou o node-canvas. Adicione-os a Permitir scripts de instalação para (formato npm:better-sqlite3) e mantêm os seus hooks.

Nota: Esta camada do proxy é independente da política de scripts de instalação do próprio npm dentro da VM. As versões recentes do npm só executam scripts de instalação para pacotes de uma lista allow-scripts, pelo que o ~/.npmrc gerido pelo Bromure em cada máquina os permite exatamente para as CLI de agentes que fornece — @anthropic-ai/claude-code, @openai/codex, @moonshot-ai/kimi-code e @oh-my-pi/pi-coding-agent — para que um agente que se atualiza com npm install -g obtenha o seu binário nativo. Todos os outros pacotes seguem a predefinição do npm. Se ativar aqui a remoção de scripts, acrescente também esses pacotes a Permitir scripts de instalação para, ou as autoatualizações dos agentes perdem o passo de instalação.

O comutador está desativado por predefinição, e aplicam-se dois limites:

  • Apenas npm. As sdists do PyPI não são reescritas — o setup.py é código arbitrário, pelo que a remoção não é viável aí.
  • Apenas instalações não fixadas. Um tarball cujo hash de integridade esteja fixado no package-lock.json não pode ser reescrito sem falhar a verificação. Esse caso é regido pela camada seguinte.

Instalações fixadas por lockfile

Uma instalação fixada por lockfile — npm ci — fixa o hash de integridade de cada tarball no lockfile. O Bromure não consegue reescrever esses tarballs sem quebrar a verificação do hash, pelo que as suas únicas opções são passá-los sem modificação ou bloqueá-los. Por predefinição, passam silenciosamente.

Se quiser ter uma palavra a dizer, ative Perguntar antes de passar sem modificação os tarballs fixados por lockfile (npm ci, pip --require-hashes) no grupo Instalações fixadas por lockfile. A primeira obtenção fixada por lockfile num lote (detetada para o npm através do cabeçalho de pedido npm-command: ci) faz então surgir uma caixa de diálogo de consentimento no anfitrião intitulada Passar npm ci (instalação fixada por lockfile) do espaço de trabalho "…"? com os botões Permitir durante 15 minutos, Permitir uma vez, Permitir durante o resto da sessão e Não permitir. Toda a rajada de obtenções concorrentes converge para esse único pedido e segue a sua decisão; negar bloqueia a obtenção com um 451 e a negação é lembrada durante 60 segundos para que as repetições não voltem a perguntar.

Nota: Apesar de a etiqueta da interface mencionar pip --require-hashes, a deteção está atualmente implementada apenas para o cabeçalho npm-command: ci do npm — as instalações pip fixadas por hash não acionam o pedido. (Também nunca são reescritas, uma vez que os artefactos do PyPI nunca são modificados.)

Confiar num pacote bloqueado

Um veredicto de reputação nem sempre é o certo para si: o socket.dev sinaliza workerd pelo seu script de instalação, e no entanto é o runtime da Cloudflare, de que o seu projeto pode precisar. Em vez de um 451 silencioso, um bloqueio do OSV ou do socket.dev no descarregamento de um pacote retém-no e pergunta: Instalar … do espaço de trabalho "…" apesar do aviso de cadeia de fornecimento?, citando a razão. As opções são:

OpçãoEfeito
Permitir … nesta sessãoInstala-o, e qualquer outra versão desse pacote, até a aplicação terminar.
Permitir sempre … neste espaço de trabalhoInstala-o e acrescenta-o à lista Pacotes confiáveis do espaço de trabalho, para que os descarregamentos seguintes saltem as verificações do OSV e do socket.dev para ele — enquanto se mantiver na lista.
Não permitir … e não perguntar de novo nesta sessãoMantém o 451; a mesma instalação continua bloqueada sem voltar a perguntar até a aplicação terminar.
Agora nãoMantém o 451 por agora; volta a perguntar ao fim de um minuto. A ausência de resposta equivale a isto.

Um veredicto de malware do socket.dev (malware, malware conhecido, malware detetado por GPT, pacote troll, chave SSH comprometida) nunca é oferecido para anulação e nunca é coberto pela lista: esses descarregamentos são sempre bloqueados. O portão de idade mantém a sua própria lista Pacotes isentos, e a remoção de scripts de instalação a sua lista Permitir scripts de instalação para — confiar num pacote aqui não o isenta de nenhuma delas.

Também pode acrescentar um pacote depois: uma linha bloqueada na Linha do tempo de segurança oferece Permitir… → Permitir sempre … neste espaço de trabalho, e a lista em si está no painel Cadeia de fornecimento, em Pacotes confiáveis (formato npm:workerd). As alterações aplicam-se de imediato a uma máquina em execução.

Pedidos de consentimento e concessões

Todos os caminhos da cadeia de fornecimento que pedem ao utilizador — a passagem direta fixada por lockfile e a retenção de pacote não verificado descrita abaixo — passam por um corretor de consentimento partilhado com convergência de rajadas: os pedidos concorrentes para o mesmo âmbito aguardam numa única caixa de diálogo em vez de empilhar alertas. A passagem direta fixada por lockfile oferece estas quatro decisões (a retenção de pacote não verificado tem as suas, por pacote — consulte Comportamento offline e degradado):

DecisãoEfeito
Não permitirBloqueia com um 451; lembrado durante 60 segundos, negando automaticamente as repetições imediatas.
Permitir uma vezDeixa passar este único pedido (ou rajada convergida).
Permitir durante 15 minutosConcede o âmbito durante 15 minutos.
Permitir durante o resto da sessãoConcede o âmbito até a aplicação sair.

As concessões e negações ativas são listadas como Decisões da cadeia de fornecimento — separadas das decisões de salvaguarda — na interface de aprovações (a área Janela → Aprovações de Credenciais…), onde pode revogar uma concessão antecipadamente. As concessões existem apenas em memória e não sobrevivem a um reinício da aplicação.

Nas sessões SSH/CLI remotas não há caixa de diálogo gráfica: a mesma pergunta é apresentada como um seletor dentro do tmux da máquina. A ausência de resposta significa negar. Ver Acesso Remoto.

Configurar a política

A política da cadeia de fornecimento é configurada por máquina, no painel Cadeia de fornecimento sob Segurança nas definições da máquina. A referência completa campo a campo encontra-se em definições da Cadeia de fornecimento; as predefinições num relance:

DefiniçãoPredefinição
Recusar pacotes mais recentes do que o limite (portão de idade)Ativado, Idade mínima: 2 dias, sem isenções
Consultar pacotes em api.osv.dev (gratuito, sem chave necessária)Desativado; Bloquear na gravidade: Alta e superior
Filtragem de pacotesNenhum (sem chave socket.dev ou Depi)
Bloquear pacotes comprometidos / Bloquear pacotes com CVEs conhecidos (socket.dev)Desativado; Limiar de bloqueio de CVE: Alta e superior
Remover preinstall / install / postinstall / prepare dos tarballs npm em tempo realDesativado, lista de permissões vazia
Perguntar antes de passar sem modificação os tarballs fixados por lockfileDesativado (passagem direta silenciosa)

Três detalhes operacionais:

  • As edições aplicam-se ao vivo. Guardar as definições envia a nova política para as sessões em execução imediatamente — o proxy lê-a a cada pedido, pelo que nunca é necessário reiniciar a VM. Cada política nova ou alterada é confirmada com um resumo de uma linha no registo da aplicação, por exemplo:

    [supply-chain] policy engaged for 1a2b3c4d: age-gate=2d osv=high socket.dev=compromised+cve=high strip-scripts
    

    As configurações incorretas são assinaladas mesmo nesse resumo: socket.dev=key-set-but-no-toggle significa que uma chave foi introduzida mas nenhum dos bloqueios está ativado, e depi=selected-but-no-key significa que o Depi está escolhido mas desativado por falta de chave.

  • Onde é armazenada. A política reside no profile.json do espaço de trabalho em ~/Library/Application Support/BromureAC/profiles/<id>/ (apenas os campos não predefinidos são escritos). As chaves de API do socket.dev e do Depi são armazenadas aí também — apenas no lado do anfitrião, mostradas como campos seguros na interface, e nunca copiadas para a VM. Não há variáveis de ambiente ou argumentos de arranque específicos da cadeia de fornecimento.

  • Configuração remota. O menu remoto SSH/TUI expõe o mesmo painel Cadeia de fornecimento com os mesmos campos, pelo que uma instância sem interface pode ser configurada sem a interface gráfica. Ver Acesso Remoto.

Acompanhar instalações na Linha do tempo de segurança

Tudo o que o pipeline da cadeia de fornecimento decide é visível na Linha do tempo de segurança — abra Janela → Segurança… ou procure-a com ⌘K. O mosaico Pacotes verificados do separador Visão geral conta as obtenções de pacotes das últimas 24 horas; clique nele, ou escolha Cadeia de fornecimento no filtro de motores do separador Linha do tempo, para as ver uma por linha.

Cada linha indica o pacote na coluna Condição (npm · [email protected]) e diz o que aconteceu na coluna Decisão, com código de cores:

DecisãoCorSignificado
verificadoVerdeA lista de versões de um pacote foi obtida e passou.
transferidoVerdeUm artefacto de pacote foi obtido e passou.
verificado — versões mais recentes do que o período de espera ocultadasAzulO portão de idade reescreveu uma lista de versões. É o portão a fazer o seu trabalho normal, não um bloqueio.
scripts de instalação removidosAzulOs hooks de instalação foram removidos de um tarball npm.
bloqueado — …VermelhoA obtenção foi recusada com um 451; a razão segue o travessão (por exemplo bloqueado — malware conhecido). Um bloqueio que pode anular tem um botão Permitir… no fim da linha.
transferido — permitido por si apesar de: …AzulUm pacote sinalizado pelo OSV ou pelo socket.dev, instalado porque o permitiu (o pedido, ou Pacotes confiáveis).

As obtenções de pacotes são sempre registadas, esteja ou não alguma camada da cadeia de fornecimento ativa — a imposição segue a política, o registo não. As instalações apt também são registadas: cada .deb obtido do pool de um arquivo Ubuntu ou Debian aparece como uma linha apt. São apenas observadas; nenhuma das verificações deste capítulo se aplica a elas.

Para o ver em ação: abra a Linha do tempo, execute qualquer instalação dentro de uma sessão (npm install, pip install, cargo add, gem install, apt install, …) e observe as linhas a chegar. Os eventos são guardados em disco durante 90 dias e sobrevivem a reinícios da aplicação; Limpar apenas oculta as linhas atuais da janela. Exportar… guarda o que o separador mostra num ficheiro CSV.

Nota: A Linha do tempo regista decisões, não cada passo. As linhas detalhadas do pipeline — cada consulta de saída, os resumos "policy engaged", os reencaminhamentos Depi, os erros de API — vão para o registo da aplicação em ~/Library/Logs/BromureAC/bromure-ac.log (e para o stderr da aplicação quando é lançada a partir de um terminal).

Comportamento offline e degradado

As verificações de reputação do pipeline dependem de chamadas de saída a partir do seu Mac (nunca a partir da VM): api.osv.dev para o OSV, api.socket.dev para o socket.dev, pypi.org para a rede de segurança do tempo de publicação do PyPI, e depi-npm-proxy.landh.tech para o Depi. Quando uma fonte ativada não consegue produzir um veredicto — rede em baixo após repetições, erro HTTP, limitação de taxa, uma falha de autenticação ou um ecossistema não suportado — o Bromure falha de forma fechada em vez de permitir silenciosamente.

O descarregamento faz uma pausa e uma retenção de pacote não verificado pergunta-lhe, num painel intitulado Instalar pacote versão do espaço de trabalho "…" sem verificação de reputação?. Diz porque não há veredicto — o socket.dev não respondeu, recusou a chave de API (verifique-a nas definições de Cadeia de fornecimento do espaço de trabalho), está a limitar a taxa da chave, ainda não terminou de analisar essa versão, ou não conhece a versão (pode ser muito recente) — e que instalá-lo significa aceitar um pacote que não foi verificado face às suas fontes de reputação configuradas. As opções:

  • Permitir pacote versão — esta versão é instalada, e não volta a perguntar durante o resto da sessão.
  • Permitir todos os pacotes não verificados por 15 minutos — este e todos os outros pacotes do espaço de trabalho que não obtenham veredicto nos 15 minutos seguintes.
  • Não permitir pacotes não verificados pelo resto da sessão — este e todos os seguintes são recusados sem perguntar.
  • Não permitir pacote versão — recusado (com um 451). Nenhuma resposta antes do fim da contagem decrescente, Esc ou fechar o painel têm o mesmo efeito.

Há uma só pergunta no ecrã por espaço de trabalho de cada vez: quando um uv sync ou um npm install encontra vários pacotes não verificados, são perguntados um após outro (o painel diz quantos estão à espera), e uma resposta para todos resolve os restantes de uma vez.

Esta é uma proteção deliberada: sem ela, um atacante que consiga induzir limitação de taxa no serviço de reputação poderia contrabandear pacotes sem verificação. As consequências práticas:

  • Trabalhar totalmente offline com o OSV ou o socket.dev ativado significa um pedido para cada pacote não guardado em cache. Desative essas camadas para períodos offline — o portão de idade continua a funcionar a partir de metadados já em cache sem conectividade.
  • socket.dev mais Cargo significa um pedido para cada crate, uma vez que o socket.dev não consegue avaliar Cargo de todo (as concessões são por pacote@versão, pelo que uma concessão de sessão cobre apenas essa versão de crate).
  • A rede de segurança do tempo de publicação do PyPI é a única exceção: num erro de rede puro, falha de forma aberta para essa obtenção (a falha não é guardada em cache, pelo que a consulta é repetida da próxima vez). A reescrita de metadados do portão de idade não é afetada.

Deteção de comprometimento

As verificações da cadeia de fornecimento reduzem as probabilidades de código hostil entrar no sandbox; a deteção de comprometimento apanha o momento em que código hostil que de facto entrou tenta agir. Faz parte do sistema de credenciais em vez do pipeline de pacotes — o retrato completo das credenciais-engodo e da troca de token está em Credenciais — mas o seu alarme é documentado aqui porque um pacote envenenado é o seu gatilho mais provável.

Cada pedido de saída da VM é examinado numa única passagem em busca dos tokens engodo ("falsos") que a camada de troca de credenciais cunhou. Um falso restringido a um anfitrião (digamos, github.com) que apareça num pedido destinado a qualquer outro anfitrião é a assinatura de exfiltração de credenciais. Quando isso acontece:

  1. O proxy bloqueia o pedido com um 451 — o destino nunca recebe um byte.
  2. A VM é pausada instantaneamente. Se a máquina estava a correr em segundo plano, é primeiro trazida para o ecrã. O fotograma congelado fica tingido de vermelho.
  3. Surge um alerta crítico, intitulado Este ambiente pode ter sido comprometido, explicando que o Bromure detetou uma tentativa de saída para vazar uma credencial de sessão da máquina nomeada para um anfitrião para o qual não foi cunhada e que a VM foi pausada — com uma linha de detalhe por vazamento: uma pré-visualização do token (como sk-a…f9q3), o nome da credencial, o anfitrião para o qual foi cunhada e o anfitrião para onde foi observada a dirigir-se.

O alerta oferece quatro respostas:

  • Desligar (a predefinição) — para a VM e marca a máquina como comprometida.
  • Bloquear — trava só este pedido e retoma a VM; o detetor volta a disparar se o agente tentar de novo.
  • Permitir — confia no anfitrião observado durante o resto desta sessão: a credencial é trocada e enviada para lá, e os pedidos para ele deixam de ser sinalizados. Use-o apenas para um destino que reconhece.
  • Salvar para investigação — escolhe uma pasta; o Bromure exporta disk.img (uma cópia do disco de sistema da VM), home.tar.gz (o diretório pessoal da máquina) e shares/<name>.tar.gz para cada pasta partilhada, depois desliga e marca a máquina como comprometida. O estado da RAM é descartado.

Só Desligar responde à tecla Return; as outras três exigem um clique explícito. Um cliente remoto que espelha a máquina recebe Desligar, Bloquear e Permitir. A descrição completa, incluindo a lista de permissões por sessão por trás de Permitir, está em Credenciais.

Uma máquina marcada como comprometida recusa-se a arrancar novamente até a limpar explicitamente, e o fluxo de limpeza avisa que as pastas partilhadas não são limpas — podem ainda conter ficheiros contaminados, pelo que as deve rever à mão.

A deteção está sempre ativa para credenciais que declaram um âmbito de anfitrião. As credenciais manuais sem um anfitrião fixado ("qualquer anfitrião") nunca a podem acionar, e os tokens Claude/Codex usam uma correspondência relaxada de mesmo domínio registado (um token cunhado para api.anthropic.com visto noutro anfitrião anthropic.com não dispara o alarme). Só é mostrado um alerta de cada vez; os eventos repetidos enquanto está aberto são descartados. Uma máquina pode suprimir o alerta e a pausa com Não alertar sobre exfiltração de credenciais no seu painel Salvaguardas; o vazamento continua a ser bloqueado e continua a aparecer como uma linha vermelha Intermediação de credenciais na Linha do tempo de segurança (ver Saídas de emergência).

Visibilidade empresarial

Para máquinas num Mac inscrito com bromure.io, cada obtenção de metadados e de artefacto também emite um evento supply_chain.fetch para o fluxo de eventos empresarial, transportando o ecossistema, o pacote, a versão, o tipo de pedido, o resultado (allowed, rewritten, blocked ou stripped) e o tipo de razão (age_gate, osv, socket_compromised, socket_cve, verify_unavailable, lockfile_denied, scripts_stripped). Só a inscrição dá aos administradores visibilidade dos descarregamentos de pacotes de toda a organização — um inventário de tudo o que cada agente instalou — mesmo em máquinas com todas as camadas de imposição desativadas.

Como funciona a inscrição, e o que os administradores veem do outro lado, é abordado em Empresa.