# 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 `///...`. 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.