~/dejafu/blog/tabnabbing
Created a day ago
Last changed a day ago

What you see is what you get (or is it not?)

Using tiptap editor, I added a feature request at my day-to-day work namely the option for users to create their own links for postings in a webapp I was working on.

While testing this feature, I expected the user created link to open in a new tab/page after clicking on it. I had configured tiptap so that the HTML attribute target="_blank" was provided to the user created link, but strangely, when rendered on the respective pages, the attribute disappeared.

I was very confused by this observation until I realized that XSS sanitization might be responsible. That is when I found out about the potential security risks of creating links with the attribute target="_blank" and how to handle this appropriately. Refer to the following github issue for more details.

Allow target="_blank"?

There is a technique called reverse tabnabbing that is made possible by links containing the attribute target="_blank". Please refer to the following documentation about this security issue on the OWASP page.

To protect users from tabnabbing, links should contain the attribute rel="noopener", in modern browsers, this is implicitly done (according to this caniuse page). If rel="noopener" does not exist in the link, the browser will handle that for you.

For my use case, I decided to add a hook to the sanitization process so that links are adjusted accordingly, whether they contain the previously mentioned attributes or not, as described here: https://github.com/cure53/DOMPurify/issues/317#issuecomment-698800327.

This looks like this:

DOMPurify.addHook("afterSanitizeAttributes", function (node) {
    // set all elements owning target to target=_blank
    if ("target" in node) {
        node.setAttribute("target", "_blank");
        node.setAttribute("rel", "noopener");
    }
});

What this means is, after sanitization is executed, link elements will get the appropriate attributes to enable opening them in new tabs/pages and prevent the potential application of tabnabbing. This was especially important for the webapp, because for organizational reasons, legacy browser versions had to be supported as well.

Thanks for checking in. See you next time!

~ jacky