Skip to content

Hardening: serve untrusted /app/* on a separate origin from /admin (same-origin risk) #878

Description

@milkway

Documented in docs/SECURITY.md, tracked here so it isn't lost: apps under /app/* are same-origin with /admin/*, so compromised app JS can issue authenticated requests to the admin. The Fetch-Metadata/Origin CSRF guard helps contra cross-site requests, but same-origin code passes that boundary by design. This makes the Disk-panel backstops (#871) mandatory, but those checks are defense-in-depth, not an isolation boundary.

Threat model confirmado

Hoje uma aplicação proxied pode servir JavaScript arbitrário sob o mesmo scheme/host/port do painel. Se um container for comprometido, uma dependência frontend estiver maliciosa ou o próprio app não for confiável, esse JavaScript pode:

  • chamar endpoints /admin/* com o cookie de sessão automaticamente anexado;
  • ler respostas same-origin;
  • executar ações POST que o usuário logado poderia executar.

HttpOnly impede a leitura do valor do cookie, mas não impede o browser de enviá-lo. SameSite=Strict, validação de Origin e Fetch Metadata também não separam dois caminhos da mesma origem. CSP no documento do admin não controla o JavaScript já executando no documento da aplicação.

Impacto

O comprometimento de um app deixa de estar restrito ao container/upstream e pode alcançar o plano de controle do Ruscker usando a autoridade de um administrador que abriu o app na mesma sessão do navegador.

Direção sugerida

Curto prazo: topologia suportada e documentada

  • Documentar uma receita oficial com pelo menos duas origens, por exemplo admin.example.com e apps.example.com (ou wildcard por app).
  • O reverse proxy deve encaminhar /admin, login e portal apenas na origem administrativa; a origem de apps deve encaminhar somente /app//api/WS e assets estritamente necessários.
  • Confirmar que cookies administrativos são host-only (Domain ausente), Secure, HttpOnly e com o menor Path viável.
  • Alertar que apenas trocar o path não cria isolamento.

Médio prazo: enforcement no próprio Ruscker

  • Adicionar configuração explícita de hosts/origins administrativos e de apps.
  • Rejeitar /admin/* no host de apps e /app/* no host administrativo, inclusive quando X-Forwarded-Host é usado.
  • Validar que forwarded headers só são confiados atrás de proxy configurado.
  • Preservar base-path, rewriting, sticky sessions, WebSocket e redirects entre as origens sem abrir CORS amplo.

Critérios de aceite

  • Existe configuração/receita suportada para separar control plane e app plane por origem.
  • A origem de apps não serve nem redireciona para endpoints administrativos autenticados.
  • Cookies administrativos não são enviados à origem de apps.
  • Testes cobrem Host/X-Forwarded-Host, base-path, HTTP e WebSocket.
  • A documentação explica por que SameSite/HttpOnly/CSRF não resolvem código malicioso same-origin.
  • Há uma estratégia de migração compatível com deploys atuais de origem única.

Prioridade sugerida: alta / security hardening, especialmente para operadores que executam imagens de terceiros ou permitem que equipes publiquem seus próprios apps.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions