What are the correct steps to import the scripts?

Before Creating a New Topic:

Actually, we are creating a custom design application and we need to import custom scripts (internal and external), so far we are having trouble implementing the chart.js library and exporting a custom .js file

This is the mistake
Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src-attr 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present.

External Scripts

we add the scripts to the content security policy

    contentSecurityPolicy: {
        directives: {
            'default-src': 'self',
            styleSrc: [ "https://fonts.googleapis.com", "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.2.0/chart.umd.js", "sha512-B51MzT4ksAo6Y0TcUpmvZnchoPYfIcHadIaFqV5OR5JAh6dneYAeYT1xIlaNHhhFAALd5FLDTWNt/fkxhwE/oQ==",  "https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/2.0.0/chartjs-plugin-zoom.min.js'", 'https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js', "sha512-B6F98QATBNaDHSE7uANGo5h0mU6fhKCUD+SPAY7KZDxE8QgZw9rewDtNiu3mbbutYDWOKT3SPYD8qDBpG2QnEg==", "nonce-2726c7f26c", ],
            scriptSrc: [ "https://appssdk.zoom.us/sdk.min.js", "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.2.0/chart.umd.js", "sha512-B51MzT4ksAo6Y0TcUpmvZnchoPYfIcHadIaFqV5OR5JAh6dneYAeYT1xIlaNHhhFAALd5FLDTWNt/fkxhwE/oQ==", "https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/2.0.0/chartjs-plugin-zoom.min.js'", "'https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js'","sha512-B6F98QATBNaDHSE7uANGo5h0mU6fhKCUD+SPAY7KZDxE8QgZw9rewDtNiu3mbbutYDWOKT3SPYD8qDBpG2QnEg==", "nonce-2726c7f26c", ],
            imgSrc: [ `https://${redirectHost}`],
            'connect-src': 'self',
            'base-uri': 'self',
            'form-action': 'self',
        },
    }, `

Internal Scripts

I create A file in /dist/js folder as contro_manager.js

and imprt using
script(src='/js/control_manager.js')

Hi @jose.sarmiento,

Are you using a package to create the CSP headers? If so, I would check out that package’s documentation.

In the case you are not using a separate package, the syntax is not correct. Raw CSP headers are strings that use semicolons to separate parts. You also do not need shas at all - that is an additional optional security feature.

See here for how the example app sets CSP headers: zoomapps-advancedsample-react/middleware.js at d4c7c9a3001a57b8b4e5e93b727d7babb8dffd31 · zoom/zoomapps-advancedsample-react · GitHub

That’s right, you should be using a nonce or a hash but not both. If you use just one do you get the same error?

Please see this document for more information:

In most cases, using the SHA hash should be the easiest to implement.

If you want to use a nonce, you can generate it uniquely and use it both in the CSP header and the client code.

Using the Basic Sample App as an example:

app.js
Generate a nonce

// generate a nonce for inlining scripts and styles
app.use((req, res, next) => {
    res.locals.cspNonce = crypto.randomBytes(16).toString('hex');
    next();
});

//...

const headers = {
    frameguard: {
        action: 'sameorigin',
    },
    hsts: {
        maxAge: 31536000,
    },
    referrerPolicy: 'same-origin',
    contentSecurityPolicy: {
        directives: {
            'default-src': 'self',
            styleSrc: [
                "'self'",
                (req, res) => `'nonce-${res.locals.cspNonce}'`,
            ],
            scriptSrc: [
                "'self'",
                (req, res) => `'nonce-${res.locals.cspNonce}'`,
            ],
            imgSrc: ["'self'", `https://${redirectHost}`],
            'connect-src': 'self',
            'base-uri': 'self',
            'form-action': 'self',
        },
    },
};

server/routes/index.js
Change the route to return the nonce you created

//...
        return res.render('index', {
            nonce: res.locals.cspNonce
            isZoom,
            title: `Hello ${name}`,
        });

server/views/index.pug
Use the variable in the client template

append scripts
    if isZoom
        script(nonce=nonce src='https://example.com/dep.js')
        script(type="module" src='/js/bundle.mjs')
        script(nomodule src='/js/bundle.js')

I hope that helps!

2 Likes

Hi @MaxM , Yeah, you are right

When I put only the chart.js in the app header and copy/paste the sha-code and put in the index.pug the same sha-code, works.

And when only use once encode, there a problem in the console

`
Refused to load the script

‘https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.2.0/chart.umd.js’ because it violates the following Content Security Policy directive: “script-src ‘self’ ‘nonce-a6c00292f4c795e4f0f0739f4a52585f’”. Note that ‘script-src-elem’ was not explicitly set, so ‘script-src’ is used as a fallback.

`

si por ejemplo,quiero añadir eventos personalizados, deberia hacer lo siguiente?=>

  1. Crear un .js con a funciones personalizadas
    ejemplo public\js\lib\control_manager.js
function myFunction(){
    const paragraph = document.getElementById('paragraph');
    // Event when the button is clicked
    paragraph.innerHTML = "new paragraph;";
}
export {myFunction}
  1. importar en el index.js
    public\js\index.js
import { myFunction } from "./lib/control_manager.js"
  1. And the import/ad event in the index .pug

button(id="myButton" onclick="myFunction()") click me

In this case the budle.js is no a module

Make sure that you are still adding the URL along with the nonce to the script-src

1 Like