Deno 2.6: dx, deno audit e permissões mais finas para a cadeia de suprimentos

O Deno 2.6 saiu em 10 de dezembro e, lendo as notas de versão, o tema que amarra quase tudo é segurança da cadeia de suprimentos. Não é uma versão de grandes rupturas: é uma versão que tapa buracos práticos do dia a dia de quem usa pacotes npm dentro do Deno. Abaixo, o que me chamou a atenção.

dx: o npx do Deno, mas perguntando antes

O novo comando dx executa binários de pacotes npm e JSR, no mesmo papel que o npx cumpre no Node. O exemplo do anúncio é dx cowsay "Hello, Deno!", e o atalho é instalado com deno x --install-alias.

As diferenças em relação a deno run importam. Segundo o blog do Deno, o dx:

  • usa --allow-all por padrão, a menos que você passe outra flag de permissão;
  • pergunta antes de baixar um pacote;
  • roda os scripts de ciclo de vida automaticamente se você aceitar a pergunta;
  • assume npm: como prefixo padrão;
  • dá erro se você passar um arquivo local.

O padrão --allow-all é a escolha pragmática para ferramentas de linha de comando, mas vale saber que ele existe. O prompt antes do download é a parte que eu considero mais útil: é exatamente o momento em que um erro de digitação no nome do pacote vira um problema.

Permissões mais granulares

Duas flags novas mudam o comportamento de recursos negados. Com --ignore-read, ler um caminho ignorado devolve NotFound em vez de NotCapable. Com --ignore-env, a variável ignorada simplesmente vira undefined, sem exceção:

deno run --ignore-read=/etc --ignore-env=AWS_SECRET_KEY main.ts

Isso é ótimo para rodar código de terceiros que tenta ler coisas “por via das dúvidas” e quebraria com um erro de permissão. Na mesma linha, Deno.env.toObject() agora respeita permissões parciais: com --allow-env=SOME_SECRET, ele retorna só essa variável.

Há também um broker de permissões experimental. Ao definir DENO_PERMISSION_BROKER_PATH com o caminho de um socket, todas as flags --allow-*, --deny-* e --ignore-* passam a ser ignoradas e cada pedido de permissão vai para o broker. É um recurso de nicho, mas abre espaço para plataformas que precisam decidir permissões de forma centralizada.

Ferramentas para dependências: audit, scripts e idade mínima

Este é o bloco mais relevante para quem mantém projetos em produção:

  • deno audit verifica dependências JSR e npm contra a base de CVEs do GitHub. A flag experimental --socket adiciona checagens do socket.dev (e usa SOCKET_API_KEY, se definida, para relatórios detalhados). A ideia declarada é falhar pipelines de CI quando houver vulnerabilidades.
  • deno approve-scripts substitui deno install --allow-scripts com um seletor interativo para aprovar ou negar scripts do tipo postinstall por pacote. As aprovações ficam salvas em allowScripts no deno.json.
  • minimumDependencyAge só permite instalar ou atualizar pacotes com uma idade mínima. Aceita minutos, duração ISO-8601 (como "P2D") ou um timestamp RFC3339, via deno.json ou --minimum-dependency-age.
  • deno install --lockfile-only atualiza o deno.lock sem baixar pacotes, útil para validar mudanças de dependências no CI.

A idade mínima é a que eu mais quero ver adotada. Boa parte dos ataques recentes a pacotes populares depende de alguém instalar uma versão comprometida nas primeiras horas. Esperar alguns dias antes de aceitar uma versão nova é uma defesa barata.

Type checking com tsgo e outras novidades

Com deno check --unstable-tsgo (ou DENO_UNSTABLE_TSGO=1), o Deno usa o tsgo, o compilador nativo do TypeScript. A equipe relata ganho de cerca de 2x em projetos internos. O suporte a tsconfig.json também melhorou para compilerOptions.paths, skipLibCheck e isolatedDeclarations.

Outros itens:

  • Source phase imports: importar o módulo compilado em vez de uma instância. Para Wasm, isso entrega um WebAssembly.Module pronto para instanciar.
  • --require pré-carrega arquivos CommonJS antes do módulo principal, complementando o --preload da 2.4.
  • @types/node passa a vir por padrão, respeitando uma versão instalada manualmente.
  • BroadcastChannel deixou de ser experimental.
  • O V8 foi atualizado para a versão 14.2.
import source addModule from "./add.wasm";

Minha leitura

O Deno sempre vendeu segurança pelo modelo de permissões, mas na prática quem usa npm acaba com --allow-all em todo lugar. A 2.6 ataca isso pelo lado certo: em vez de só endurecer as permissões, dá ferramentas para controlar o que entra no projeto (audit, aprovação de scripts, idade mínima) e torna as permissões negadas menos quebradiças com --ignore-*.

A ressalva é que vários desses recursos são novos ou experimentais (--socket, o broker, o tsgo), então eu testaria em CI antes de depender deles. Mesmo assim, minimumDependencyAge e deno audit são coisas que eu ativaria hoje em qualquer projeto Deno.

Fontes