Description
Bug description:
When using a strict CSP policy, then unsafe inline javascript is disallowed and whenever executed an error message appears in the logs:
Refused to run the JavaScript URL because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-random_nonce_val'". 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.
Versions of ngx-bootstrap, Angular, and Bootstrap:
- ngx-bootstrap: 18.1.3
- Angular: 18
- Bootstrap: 4.6
Expected behavior
I noticed this with the Carousal component, where the control buttons (left / right) use the following javascript inline in the href attribute: javascript:void(0);
A quick search reveals that the following components are affected by this: tabset, timepicker, carousel, sidebar
Another quick look on the components on bootstrap (just for the Carousel) it looks like bootstrap 5 is actually using button
instead of a
.
Bootstrap 4 is using a href with the anchor to the carousel id element (e.g.: href="#carouselExampleControls"
) and I assume the jQuery has a listener which returns false on click to prevent the anchor messing around with the navigator address.
My proposal would be to update the components and use buttons instead of a
elements (as the official bootstrap 5 documentation does).
Another solution would be to use a dummy anchor #
and return false
in the onclick
handler. (see my workaround below)
Currently I use the following workaround for the Carousel component, by using a wrapper component:
import { AfterViewInit, Component, ElementRef } from '@angular/core';
@Component({
selector: 'app-slider',
templateUrl: './slider.component.html',
})
export class SliderComponent implements AfterViewInit {
constructor(private readonly myElement: ElementRef) {}
ngAfterViewInit(): void {
const aTags = (this.myElement.nativeElement as Element).querySelectorAll('a.carousel-control') as NodeListOf<HTMLAnchorElement>;
aTags.forEach((aTag) => {
aTag.href = '#';
aTag.onclick = () => false;
});
}
}
This will prevent errors in the console and behaves like the original version.
NOTE: function vise everything works fine, it's just an ugly error in the console. 👍