prometeu-runtime/docs/pull-requests/PR-004-runtime-vfs-path-traversal-hardening.md

3.9 KiB

PR-004: Runtime VFS Path Traversal Hardening

Briefing

Hoje o VirtualFS normaliza barras, mas nao canonicaliza nem rejeita segmentos ... Em seguida, o backend de host concatena o caminho recebido com a raiz montada. Isso abre espaco para escapar da raiz virtual com caminhos como /user/../../outside.txt.

Este PR endurece a fronteira entre o filesystem virtual e o filesystem do host. O objetivo e garantir que toda operacao de read/write/delete/list/exists permaneça estritamente dentro da raiz montada.

Problema

  • O VirtualFS aceita caminhos relativos e absolutos sem validacao estrutural suficiente.
  • O backend HostDirBackend faz root.join(path) sem bloquear traversal.
  • O problema afeta confidencialidade, integridade e isolamento do runtime.

Escopo

  • Endurecer a normalizacao de caminhos no VirtualFS.
  • Endurecer a resolucao no HostDirBackend.
  • Garantir comportamento consistente para read_file, write_file, delete, list_dir e exists.
  • Cobrir casos de traversal em testes unitarios.

Fora de Escopo

  • Suporte a links simbolicos com politicas avancadas.
  • Politicas de permissao por namespace (/system, /user, /apps, etc).
  • Refactor completo da API de filesystem.

Abordagem

  1. Introduzir uma regra unica de validacao de caminho virtual:
    • converter \ para /;
    • exigir caminho absoluto virtual;
    • colapsar . quando aparecer;
    • rejeitar qualquer segmento vazio ambiguo ou ..;
    • retornar erro explicito em vez de tentar "corrigir" traversal.
  2. Fazer o VirtualFS operar apenas sobre caminhos validados.
  3. Endurecer o HostDirBackend para nunca confiar apenas na normalizacao acima:
    • resolver o caminho relativo a partir da raiz;
    • rejeitar novamente qualquer tentativa de escapar;
    • manter defesa em profundidade mesmo se outro backend ou chamador evoluir errado.
  4. Garantir que operacoes booleanas como exists nao silenciem traversal como se fosse "arquivo inexistente" sem distinguir erro estrutural quando isso for relevante para a API.

Algoritmo

Normalizacao de caminho virtual

Entrada: path: &str

Saida: caminho virtual sanitizado ou erro.

Passos:

  1. Substituir \ por /.
  2. Se o caminho nao comecar com /, prefixar /.
  3. Separar por /.
  4. Ignorar segmentos vazios e ..
  5. Se algum segmento for .., falhar com FsError.
  6. Reconstruir o caminho como /<seg1>/<seg2>/....
  7. Preservar / como raiz quando nao houver segmentos.

Resolucao no backend do host

Entrada: caminho virtual sanitizado.

Saida: PathBuf dentro de root ou erro.

Passos:

  1. Remover o / inicial do caminho virtual.
  2. Concatenar cada segmento validado manualmente em um PathBuf iniciado em root.
  3. Nunca aceitar segmentos .., . ou componentes de prefixo/plataforma.
  4. Antes de retornar, garantir que o caminho construido continua sob root.

Criterios de Aceite

  • Qualquer tentativa de traversal com .. e rejeitada em read_file.
  • Qualquer tentativa de traversal com .. e rejeitada em write_file.
  • Qualquer tentativa de traversal com .. e rejeitada em delete.
  • exists e list_dir nao acessam caminhos fora da raiz montada.
  • Caminhos normais como /user/save.dat continuam funcionando.
  • O backend de host continua criando subdiretorios validos dentro da raiz.

Tests

  • Teste unitario no VirtualFS para rejeitar:
    • ../x
    • /../x
    • /user/../../x
    • \\user\\..\\..\\x
  • Teste unitario no backend do host validando que um caminho de traversal nao resulta em acesso fora da raiz temporaria.
  • Teste positivo para operacoes validas:
    • criar arquivo em /user/test.txt;
    • ler o mesmo arquivo;
    • confirmar exists;
    • apagar o arquivo.
  • Rodar:
    • cargo test -p prometeu-system
    • cargo test -p prometeu-host-desktop-winit

Risco

Baixo para a arquitetura e medio para compatibilidade, porque caminhos hoje aceitos de forma permissiva podem passar a falhar explicitamente. Esse endurecimento e desejado.