Permission Model do Node.js: Restringindo Acesso com --permission

Como o Permission Model do Node.js bloqueia por padrão o acesso a arquivos, processos filhos e workers, liberando apenas o necessário com flags --allow-* e verificando permissões com process.permission.has().

Por padrão, qualquer script Node.js pode ler e apagar arquivos, abrir processos filhos e carregar addons nativos com as mesmas permissões do usuário que o executou. Isso inclui cada dependência dentro de node_modules. O Permission Model, ativado com a flag --permission, inverte essa lógica: tudo começa bloqueado e você libera só o que a aplicação realmente precisa.

Ativando o modelo de permissões

Com --permission, o acesso ao sistema de arquivos, a criação de processos filhos, worker threads, addons nativos e WASI ficam bloqueados. Considere um script que lê uma configuração e grava um log:

// app.js
import { readFileSync, writeFileSync } from 'node:fs';

const config = readFileSync('./config/app.json', 'utf8');
writeFileSync('./logs/inicio.log', `Iniciado em ${new Date().toISOString()}\n`);

console.log('Configuração carregada:', JSON.parse(config).nome);

Rodando com o modelo ativado e sem liberar nada, a leitura da configuração é barrada:

node --permission app.js
# Error: Access to this API has been restricted. Use --allow-fs-read to manage permissions.
#   code: 'ERR_ACCESS_DENIED',
#   permission: 'FileSystemRead',
#   resource: '.../config/app.json'

O arquivo de entrada (app.js) é liberado para leitura automaticamente. Todo o resto precisa ser concedido de forma explícita.

Liberando apenas o necessário

As flags --allow-fs-read e --allow-fs-write recebem caminhos relativos ou absolutos. Se o caminho for um diretório existente, tudo dentro dele fica liberado:

node --permission \
    --allow-fs-read=./config \
    --allow-fs-write=./logs \
    app.js

Agora o script lê qualquer arquivo de ./config e grava em ./logs, mas uma tentativa de ler ~/.ssh/id_rsa ou sobrescrever package.json falha com ERR_ACCESS_DENIED. As outras capacidades têm flags próprias:

Versões mais recentes também incluem flags para outras capacidades, como acesso à rede — vale conferir a lista completa na documentação da versão que você usa.

Verificando permissões em tempo de execução

Com o modelo ativo, process.permission.has() informa se uma permissão foi concedida, opcionalmente para um recurso específico. Isso permite degradar de forma elegante em vez de deixar a aplicação quebrar:

import { writeFileSync } from 'node:fs';

function salvarCache(caminho, dados) {
    if (process.permission && !process.permission.has('fs.write', caminho)) {
        console.warn(`Sem permissão de escrita em ${caminho}; cache desativado.`);
        return false;
    }

    writeFileSync(caminho, JSON.stringify(dados));
    return true;
}

salvarCache('./logs/cache.json', { atualizadoEm: Date.now() });

O teste process.permission && ... mantém o código funcionando também quando o script roda sem --permission, caso em que process.permission não existe.

Configurando no package.json

Como as flags ficam longas, o lugar natural delas é um script do package.json:

{
  "scripts": {
    "start": "node --permission --allow-fs-read=./config --allow-fs-write=./logs app.js"
  }
}

Casos de uso

Cuidados

A documentação descreve o modelo como um "cinto de segurança": ele impede que código confiável acesse sem querer o que não deveria, mas não é uma sandbox contra código malicioso. Links simbólicos são seguidos mesmo para fora dos caminhos liberados, operações em descritores de arquivo já abertos não passam pela checagem de caminho e as permissões não são herdadas por worker threads. Para isolar código não confiável, continue usando containers ou processos separados.

Compatibilidade

O Permission Model surgiu no Node.js 20 como experimental, atrás da flag --experimental-permission. Ele deixou de ser experimental, com a flag --permission, no Node.js 23.5.0, com backport para o Node.js 22.13.0 (LTS). A flag antiga --experimental-permission foi removida de vez no Node.js 24.

documentação oficial

Conclusão

O Permission Model traz para o Node.js o princípio do menor privilégio: com --permission e algumas flags --allow-*, cada aplicação declara exatamente o que pode ler, escrever e executar. Não substitui o isolamento por containers, mas é uma camada extra barata que reduz o estrago de um bug ou de uma dependência mal-comportada.

Tecnologia:
node

Deixe seu Comentário!

Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.

Comentário
Nome
Email
lock Seu e-mail não será publicado.