Skip to content

CSP issues (unsafe inline script) with "javascript:void(0);" #6718

Open
@TheDelta

Description

@TheDelta

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. 👍

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions