J’ai justement identifié la source de ce problème avec le plugin d’intégration (embed). Lors de la configuration de l’intégration, il existe un paramètre « Hosts autorisés » qui définit ensuite la CSP pour l’iframe ; cette dernière ne s’affiche alors que sur l’hôte spécifié. Par exemple, si je configure les intégrations avec un hôte autorisé example.com et que j’essaie d’intégrer le JS sur attacker.com, l’iframe refuse de se charger avec l’erreur suivante :
Refused to frame 'https://forum.example.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' https://example.com".
Cependant, à ce stade, le JS a déjà été exécuté et a créé un sujet sur le forum avec l’URL fournie au code d’intégration.
Dans mon cas, ce qui se produit, c’est que nous utilisons Netlify pour prévisualiser les builds, si bien qu’une copie du blog est effectivement servie depuis des URL netlify.app. Celles-ci chargent alors ce embed.js et créent le fil de discussion du forum pour les articles que j’avais précédemment importés de manière incorrecte.
Il ne s’agit pas nécessairement d’un problème de sécurité, car cela ne permet toujours de créer des sujets que pour des URL du site configuré et correspondant à la liste blanche des chemins. C’est toutefois un problème dans le cadre de cette stratégie de migration, car je n’avais aucun moyen de définir l’attribut embed_url sur les fils de discussion du forum lors de l’importation d’anciens articles vers Discourse.
La solution consiste à ajouter une règle CSP pour empêcher l’exécution de ce embed.js sur des domaines qui ne sont pas configurés dans le paramètre « hosts autorisés ».
À titre de preuve de concept, j’ai copié le code d’intégration sur un domaine totalement sans rapport et j’ai défini discourseEmbedUrl sur l’un des anciens articles que j’avais importés. J’ai chargé la page : l’iframe a été bloquée, mais le JS avait déjà été exécuté et avait créé le fil de discussion du forum.
Si vous estimez qu’il s’agit davantage d’un problème de sécurité que d’un bug, je suis prêt à supprimer ce message et à le signaler via HackerOne à la place.