103 lines
3.9 KiB
Markdown
103 lines
3.9 KiB
Markdown
# 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.
|