Acabei de rastrear a origem desse problema com o plugin de embed. Ao configurar o embedding, há uma configuração chamada “Allowed Hosts” (Hospitais Permitidos), que define o CSP para o iframe, fazendo com que o iframe apareça apenas nesse host. Por exemplo, se eu configurar os embeds com um host permitido de example.com e tentar incorporar o JS em attacker.com, o iframe se recusa a carregar com o erro:
Refused to frame 'https://forum.example.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' https://example.com".
No entanto, o JS já havia sido executado nesse momento e criou um tópico no fórum com qualquer URL fornecida ao código de embed.
No meu caso, o que está acontecendo é que usamos o Netlify para pré-visualizar builds, então uma cópia do blog está sendo servida a partir de URLs netlify.app, que estão carregando esse embed.js e criando a thread do fórum para as postagens que eu importei incorretamente anteriormente.
Isso não é necessariamente um problema de segurança, pois ainda é possível criar tópicos apenas para URLs no site configurado e que correspondam à lista de permissões de caminho. Mas é um problema nesta estratégia de migração, já que não havia como definir o embed_url nas threads do fórum ao migrar postagens antigas para o Discourse.
A solução é adicionar uma regra CSP para impedir que o embed.js seja executado em domínios que não estejam configurados na configuração de “allowed hosts”.
Como prova de conceito, copiei o código de embed para um domínio completamente não relacionado e defini o discourseEmbedUrl para uma das postagens antigas que importei. Ao carregar a página, o iframe foi bloqueado, mas o JS já havia sido executado e criado a thread do fórum.
Se você achar que isso é mais um problema de segurança do que um bug, ficarei feliz em excluir esta postagem e relatá-lo através do HackerOne.