Make it possible to use without CSP style-src 'unsafe-inline' aka without loading inline CSS into the component

Author: rugkCreated Mar 7, 2025Updated Oct 14, 2025

STR

I use this content security policy (CSP) (in my case in a browser extension, but it can likewise be done on any website):

csp
default-src 'self'; img-src data:; style-src 'self' https://unpkg.com; script-src 'self' https://unpkg.com

The setup is quite minimal and basically boils down to your Readme browser example with some (you can ignore/remove the settings, they do not matter):

javascript
export function init(settings) {
    const initProperties = Object.assign(settings, hardcodedSettings);
    initProperties.emojiButtonSize = initProperties.emojiSize + 12;

    console.debug("Using these emoji-mart settings:", initProperties);

    const emojiPicker = new EmojiMart.Picker({ ...initProperties, data: async () => {
        const response = await fetch(browser.runtime.getURL(`/node_modules/@emoji-mart/data/sets/${initProperties.emojiVersion}/${initProperties.set}.json`));

        return await response.json();
    }});

    // NOTE: Typing is not updated yet, so cannot be used here: https://github.com/missive/emoji-mart/issues/576
    // @ts-ignore
    document.body.appendChild(emojiPicker);
    console.info("Created EmojiPicker component:", emojiPicker);
}

What happens

Now if you do this, you get a CSP error:

Content-Security-Policy: Die Einstellungen der Seite haben die Anwendung eines Inline-Styles (style-src-elem) blockiert, da er gegen folgende Direktive verstößt: "style-src 'self' https://unpkg.com/"

Roughly translated as:

Content security policy: The page settings have blocked the use of an inline style (style-src-elem) because it violates the following directive: ‘style-src “self” https://unpkg.com’

And for obvious reasons the CSS/style is not applied, so it looks horribly broken:

Image

Workaround

Adding 'unsafe-inline' to style-src fixes it aka:

csp
default-src 'self'; img-src data:; style-src 'self' 'unsafe-inline' https://unpkg.com; script-src 'self' https://unpkg.com

What should happen

Anyway, IMHO, this is no real solution. Instead, it should best work with the strictest CSP possible. For security reasons... because otherwise it prevents such a strict CSP everywhere on the site (unless some clever tricks may be used, but well). 'unsafe-inline' is indeed unsafe and should be avoided if possible. And all in all, the aim of CSP is to prevent XSS attacks. When a component forces you to weaken the CSP, that is not good, IMHO.

Now, I don't know whether this can be solved or if this is some thing custom elements usually require? Or maybe similar to how the images/sprites delivery can be overwritten, you can also do so?

System

Firefox 135.0.1 Linux/Fedora 41

More information

Related: https://github.com/missive/emoji-mart/issues/420 is the only other CSP "bug" I have found. There, the reason is obvious though, and as I've shown I already load and bundle the images locally. And even if I would not, the https://unpkg.com is and can be included in the CSP.