webdevnerdstuff / vue-code-block

Vue 3 CodeBlock - Highlight your code with ease using this syntax highlighting component powered by PrismJS or Highlight.js.
https://webdevnerdstuff.github.io/vue-code-block/
MIT License
34 stars 3 forks source link

[Bug Report]: Avoid reliance on CDN for .css #24

Closed tommed closed 8 months ago

tommed commented 8 months ago

Bug description

We have a GUI which is accessed by high-security customers, so the CSP policies and firewall requirements ideally need to be as self contained as possible.

Your implementation makes use of external CDNs like so:

const highlightCdn = ref(`https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@${highlightJsVersion}/build/styles`);
const prismCdn = ref(`https://cdn.jsdelivr.net/gh/PrismJS/prism@${prismVersion}/themes`);
const prismThemesCdn = ref(`https://cdn.jsdelivr.net/gh/PrismJS/prism-themes@${prismThemesVersion}/themes`);

We'd ideally like to use the NPM package manager and include these resources internally in our product. This will avoid needing to open up CSP and other firewalls to allow resources from https://cdn.jsdelivr.net from being permitted.

The risk here is that a malicious actor would inject code which runs scripts hosted on this CDN. Our CSP and firewall policy would not be able to stop this because we've made this permissive to get this product working.

If we were to use the highlightjs npm library without your vue implementation, this requirement isn't needed.

Steps to reproduce

Above above.

Relevant log output

AutomationGuideView-657bdc62.js:39 Refused to apply inline style because it violates the following Content Security Policy directive: "default-src 'self' https://apis.vipro.online https://apis.panessex.co.uk". Either the 'unsafe-inline' keyword, a hash ('sha256-SATV5v6C5TBYjsYpJqHI2uZmBVvLsFXgo77cQmxyvlQ='), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.

(anonymous) @ AutomationGuideView-657bdc62.js:39
AutomationGuideView-657bdc62.js:38 Refused to connect to 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/styles/github-dark-dimmed.min.css' because it violates the following Content Security Policy directive: "default-src 'self' https://apis.vipro.online https://apis.panessex.co.uk". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.

aa @ AutomationGuideView-657bdc62.js:38
AutomationGuideView-657bdc62.js:38 Refused to connect to 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/styles/github-dark-dimmed.min.css' because it violates the document's Content Security Policy.

Additional context

With CSP blocking the external CDN resources, the plug-in actually looks like this:

image

Code of Conduct

webdevnerdstuff commented 8 months ago

The problem with using the npm package is that the css file cannot be fetched outside of the web root, which is needed if changing the styles (for example switching from light/dark modes).

The reason the highlight.js implementation works is it a self hosted css file (or via a CDN). On their demo page, they actually load a css file with all themes included (https://highlightjs.org/demo), which makes sense for their demo, but for any normal project that uses one theme, a self hosted file of the specific theme makes more sense.

I've opened up a discussion as I think this is something that could be improved upon. https://github.com/webdevnerdstuff/vue3-code-block/discussions/25

tommed commented 8 months ago

Understood thanks. Could you not offer an overload which allowed it to be self-hosted on a domain suitable for the installation rather than forcing the CDN to be used? This would allow us to host it within our official domains, but also allow the functionality you describe.

I suspect there may be something possible with the bundler to achieve what you're describing, but it's not really an area I've spent much time in, so I'll work on the premise that the CSS needs to be hosted separately.

webdevnerdstuff commented 8 months ago

@tommed I added a new cssPath prop that you can use to link to the location of your choice. Please be aware that I have updated this repo and it's npm package to my scoped npm name. Also if you like this package please give me a star #selfPromotion :)

New npm package location: https://www.npmjs.com/package/@wdns/vue-code-block

tommed commented 8 months ago

This works great, thank you so much!

The only other CSP issue was the need to use 'unsafe-inline' style-src as it writes CSS inline. This is unfortunate, but given it's CSS and not JScript, we will just have to justify an exception for this behaviour for each of our customers when they do pen. testing. Unless there's something that can be done about this...?

This is the CSP required to make your code block work:

style-src 'self' 'unsafe-inline';

Ideally obviously, "unsafe" wouldn't normally be needed! ha ha ;)

webdevnerdstuff commented 8 months ago

Perhaps in a future release or refactoring I can try to work around inline styles. Most of the inline styles don't necessarily need reactivity I think. But it's definitely something I should keep in mind.