jquery.terminal
jquery.terminal copied to clipboard
CSP warnings on strict CSP
Hi,
I'm getting some CSP warnings like
Refused to apply inline style because it violates the following Content Security Policy directive
if I include the terminal in my site. I'm using a rather strict CSP for style-src with only self and a nonce value. The error futher reads
Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.
so I can't use unsafe-inline to mitigate this. Despite the warnings,, the terminal works flawlessly, but I would like to remove them. Is there any way to achive this?
Sorry but you can't have fully working terminal without inline CSS they are require to make terminal work properly. You will need to change the CSP so it accept inline styles. Maybe you can do something else can I include some how the hash or nonce as option? I'm not that familiar with working of CSP.
I don't think that just adding a nonce option will work. There are many usages like $.css in the code, which would need to be rewritten to add a <style> tag with the given nonce. I counted like 20+ code lines which rely on inline-styles.
I think setting unsafe-inline for style-src should just be noted in the README until the terminal can be used without it.
It's impossible what You requested the library have dynamic custom properties it will be very hard to to just swap everything with inline styles. I can add info about CSP in Readme or in docs in security section.
As a workaround you can host the terminal code on different domain with unsafe-inline (or don't use CSP at all) put it into iframe and contact with postMessage.
If you really really need that this library have <style> instead of inline css because of your settings you can always take time and change the library so it work that way. But you will need to spent lot of time rewriting it and at the end it will trun out that the library don't work and tests don't pass. If you want you can check if it will work but I think it will be complicated you will need to create class like terminal-instance-01/02/03 and put style for given terminal. The only thing I can do is to add API (like css function and add terminal-instance classes to terminals) but you will need to do the work yourself.
After second thought I think this is something that can be added to the library. All you will need to use is nonce options:
$('body').terminal({
...
}, {
nonce: 'w51UFM0uev/LhCA+J2h7Bw=='
});
and the library will add inline style with that nonce:
<style nonce="w51UFM0uev/LhCA+J2h7Bw==" data-terminal="2.19.0">
</style>
There can be single inline style, but this may take a while before it's implemented.
NOTE: you will not be able to use any formatting except class with jQuery Terminal. So no unix_formatting, prims will work because it's class based. For this it will be very huge task that make it working. But you will be able to use formatting if you only change the class and you will need to create your own colors and styles inside classes.
For reference: https://web.dev/strict-csp/
Probably the best way is to do a similar thing what styled-components do:
<div id="12aifc" class="terminal">
<style nonce="w51UFM0uev/LhCA+J2h7Bw==">
#12aifc {
--char-width: 7.23438;
}
#12aifc .cmd {
width: 100%;
--cursor-line: 0;
top: 0px;
}
</style>
</div>
Here is the code that generates a simple hash.
// -----------------------------------------------------------------------------
// :: ref: https://gist.github.com/jlevy/c246006675becc446360a798e2b2d781
// -----------------------------------------------------------------------------
function hash_number(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash &= hash; // Convert to 32bit integer
}
return hash;
}
function hash(str) {
var hash = hash_number(str);
return new Uint32Array([hash])[0].toString(36);
}
var id = hash(new Date().toString());
TODO:
- test if calling multiple terminals with same selector create unique hash
NOTE: if users that need CSP want to have formatting they will need to use classes.
[[;yellow;]hello]
will need to be:
[[;;;yellow]hello]
.yellow {
color: yellow;
}
This can be added to Wiki. A style like [[bi;;]text] can be handled by classes, that will not be that hard.
Revisiting this, with a new idea from styled components. To make formatting work you only need to update $.terminal.format function to generate identifiers for each span and use the style tag to add style. This will be a fundamental change maybe this can be done for version 3.0 of jQTerm.
Created a proof of concept jQuery plugin $.fn.style that adds style to elements with strict CSP.
The user code look like this:
const nonce = '2726c7f26c';
$('<p>This is Styled Text</p>').style({
color: 'blue',
background: 'darkgrey',
padding: 10
}, nonce).appendTo('body');
$('<p>This is Styled Text</p>').style({
color: 'blue',
background: 'darkgrey',
padding: 10
}, nonce).appendTo('body');
Here is the full gist.
The code uses nonce value that can be generated by the backend and will be passed to the library.
Here is a live demo CSS-in-JS-with-CSP.html