issue with an article using document.createElement("script") giving me an error

Loading Script Files Dynamically

hello - when i enter the following lines from this article:

let myScript = document.createElement("script");
myScript.setAttribute("src", "https://cdn.socket.io/4.5.3/socket.io.js");
document.body.appendChild(myScript);

i receive the following error:

VM78:3 Refused to load the script ‘https://cdn.socket.io/4.5.3/socket.io.js’ because it violates the following Content Security Policy directive: “script-src chrome://resources chrome://test chrome://webui-test ‘self’”. Note that ‘script-src-elem’ was not explicitly set, so ‘script-src’ is used as a fallback.

please let me know what i am doing wrong?

I’d just use Import() mate.

https://youtu.be/IhWpL0g3QME

@Mark_Edwards - glad you were able to resolve this!

I am very surprised that setting script.type fixed this issue, for it is an optional parameter: <script>: The Script element - HTML: HyperText Markup Language | MDN It made a lot of sense when one could have both vbscript and javascript as options, but that was decades ago!

Though, I’m sure others here like @senocular may have a much better answer for this :slight_smile:

DANG - spoke WAY too soon here…

[ ‘//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js
, ‘//unpkg.com/@feathersjs/client@^3.0.0/dist/feathers.js
].forEach( (src) => {
let script = document.createElement(‘script’);
script.setAttribute(‘crossOrigin’, ‘anonymous’ );
script.type = ‘text/javascript’
script.src = src;
script.async = false;
console.log(script);
document.head.appendChild(script);
});

this is still giving me the same error:
Refused to load the script 'chrome://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js' because it violates the following Content Security Policy directive: "script-src chrome://resources chrome://test chrome://webui-test 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

i got a little bit further: if we start with an empty html page:

<html>
<head></head>
<body></body>
</html>

then it works fine. however, if i just open up a new tab, and/or enter about:blank it does not work, even though the html is identical.

If you try with any other JS file, does the example script for loading a JS file work?

For a working example, view source on kirupa.com for an example where I load our docsearch search capability using this approach.

My hunch is, as the error is explaining, possibly related to a CORS issue where the server the script you are trying to load disallows third parties from loading it.

(I would share the snippet directly, but I am on my phone :grinning:)

ok i THINK I solved it…

  1. open up about: blank in a new tab

  2. enter the following in the console:

[ 'https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js'
, 'https://unpkg.com/@feathersjs/client@^3.0.0/dist/feathers.js'
].forEach( (src) => {
    let script = document.createElement('script'); 
    script.setAttribute('crossOrigin',  'anonymous' );  /*optional */
    script.type = 'text/javascript'                 ;   /* optional */
    script.src =  src;
    script.async = false; 
    console.log(script);
    document.head.appendChild(script);
});

i think the issue is specifying the https: – maybe normally about:blank defaults to “chrome:” or something odd like that.
(and this problem has been a nice way to ruin an evening…:persevere: )

Is the site you are running this code from also on a https domain?

no it is not! this code i am running is cut/pasted directly into the browser console, so there really is no webpage at all, its like standalone client-side javascript.

in case you are wondering why:
i am using feathersJS (its totally wonderful and awesome!) and with this code, i can “connect” to my feathersJS server and test it. yes its true i can do the same thing with Postman, but this way i can develop my js code without yet even having a working webpage.

1 Like

That is a really interesting use-case! :slight_smile:

I got interested in this for dumb reasons.
The code from your first post works in Chrome:new tab and about:blank , FF: about:blank. But it doesnt work in FFs new tab as its html sets some cors in the head. So why you got those errors in the first post doesnt make much sense? Where did those content security settings come from? chrome://resources could make sense, but where did
chrome://test and chrome://webui-test come from? Maybe you have some extension doing something?..although if I remember right (havent done extensions in a long time) extensions cant target the ntp, only replace it.
If your to lazy to open an editor, the cli and run a server (I sure am) then just use a site like JsBin or woteva.
Tested on windows/pc.

PAEz: doing a cut-paste from my notes right into the browser console is the fastest way for me to test.

kirupa: if you saw the 20’ish lines of code necessary to CRUD data from MariaDB/PostgreSQL/cockroachDb, etc, and then see your data in a JSON format right in your browser console, you too would be totally amazed!

i am actually one of the sponsors of feathersJS. this was after taking the long and difficult journey through rails-trails-snails, meteor, meatier (yes that’s a thing) and deepStream :tired_face:, i finally found feathersJS.

feathersJS really “combines” your favorite ORM (i prefer Knex, formally i used sequelize) with express(socket-io). It’s the only framework i have looked at that actually makes sense to my limited brain. and the built-in security uses Auth0 - its just totally amazing!

so besides initially loading a couple of libraries via cut-paste, this code below retrieves data from your predefined SQL statement (assuming your simple feathersJS server is running of course, and you have also created a feathersJS “service” called “tiny-connect”)

async function getTiny(id) {      
  let getResult = await app.service('tiny-connect').get(id); 
  console.log('getTiny function: ' + JSON.stringify(getResult) ); 
  return getResult; 
}; 

let getTinyResult = null; let key = 1;   // assuming your row ID is one
getTiny(key).then( value => {      /* get(GET) */ 
  getTinyResult = value; 
  console.log('getTiny(' + key + ') : ' + JSON.stringify(getTinyResult) ); 
});

so my thinking is get the UI completed (using fake JSON data) , then just drop in a few of these feathersJS promises to replace the fake JSON.

side-note: i am an old SQL kinda guy. the feathersJS people seem to be against using ordinary SQL – but all my old apps use it, so i can just grab the preexisting SQL, wrap a little bit of feathers server around it, and near instantly my SQL results are available to me in the browser console. most of the feathersJS people are against using “raw SQL” for whatever reason. trying to rewrite a multiple left-join SQL in Knex hurts my head even just trying to consider doing it.:smirk:

Really? So wasting a night on simple code that works is the fastest way for you? That code was simple and works. The only reason it didnt work was because of the environment it was executed in. The HTML for a new tab page is NOT empty, it has a lot of code already. And the blank page normally does work, so god knows what was going on for you. The only time an ntp shouldnt be blank is if youve changed it. In FF you can set it to what ever in settings, in Chrome you need to make an extension to change it. This is why I suggested to use something that is consistent. The other thing you could have done to avoid wasting a night was to follow the tutorial to the letter. Next time it tells you to open a console on the feathers default page then do that, not some other page. The reason I know what tutorial you where looking at is coz Im actually interested in Feathers myself and knew that an app.service is something you make yourself and went looking for what tiny-connect was. Feathers is cool tho huh? I just wanna use it to simplify socketio stuff amongst other things.

PAEz raises some excellent considerations here. I found myself too “stuck” on something that has traditionally worked fine for me for many years, and is referenced in many stack overflow solutions.
Here is another solution that might be a fair compromise to the situation where “about:blank” is not working as expected:

#!/bin/bash -w
#
#       2022-11-24
#
#       simulate a webserver & include script libraries in case
#       of the chrome "about:blank" is not working
#
#      2022-11-25 - changed ncat command to run in background
#
/usr/bin/cat <<END  |  /bin/ncat --listen 80  &
<!DOCTYPE html>
<html lang="en-us">
<head>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js'></script>
  <script src='https://unpkg.com/@feathersjs/client@^3.0.0/dist/feathers.js'></script>
</head>
<body>
  fake webserver page.  include extra jScript code in the console.
</body>
</html>
END

Google has a rich history of changing rules regarding SSL webpages. It’s happened more than once that a rule will be enforced where i had completely missed several months of warnings in the console. Naturally, i just assumed this was yet another one of the SSL rules now being forced, but my original issue appears to be a bit more complicated than that. However, I believe that these two workarounds should suffice.

Thank you all for your time and consideration.