Skip to content

ng-event-dispatch-contract script execution blocked on apps with CSP via CSP_NONCE token #66540

@WizzardMaker

Description

@WizzardMaker

Command

build

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

I wanted to add Content-Security-Policy to my app and found that the CSP_NONCE token way to implement it looked to be the easiest with SSR.
The nonce is generated in the express route handler and provided to the app with the REQUEST_CONTEXT and TransferState.
Every angular script and style is correctly appended with that nonce, just the "ng-event-dispatch-contract" script is missing the nonce.

I want to generate the nonce myself because the app uses a few custom scripts at runtime that require the nonce

Minimal Reproduction

  1. Create app with SSR enabled
  2. Set route to RenderMode.Server
  3. Add (click) handler to any component (required or else the script gets removed before send)
  4. Add CSP nonce token to client and server (just to replicate the current project, I think it should also work only server side)
function provideCSPNonce() {
  return {
    provide: CSP_NONCE,
    deps: [TransferState, REQUEST_CONTEXT],
    useFactory: (transferState: TransferState, rq : any)=>{
      if(!!rq){
        const nonce = rq.nonce;
        transferState.set(CSP_NONCE_TRANSFER, nonce);
        return nonce
      }else{
        return transferState.get(CSP_NONCE_TRANSFER, null);
      }
    }
  }
}
  1. Add CSP and nonce to headers and request context:
/**
 * Handle all other requests by rendering the Angular application.
 */
app.use(async (req, res, next) => {

  const resp = await angularApp.handle(req, {
    nonce: 'test123'
  })
  if(!resp)
    return next();

  resp.headers.set("Content-Security-Policy", `default-src 'self'; script-src 'self' 'nonce-${'test123'}';`);
  await writeResponseToNodeResponse(resp, res);
});

Exception or Error

The browser will complain, that the ng-event-dispatch-contract script does not have a nonce:

Executing inline script violates the following Content Security Policy directive 'script-src 'self' 'nonce-test123''. Either the 'unsafe-inline' keyword, a hash ('sha256-VM2mZqyEQZoLzoTrp5EigFvzQ0+f1wSeBuoOn95WHCg='), or a nonce ('nonce-...') is required to enable inline execution. The action has been blocked.

Your Environment

Angular CLI: 20.3.14
Node: 24.9.0
Package Manager: npm 11.6.0
OS: darwin arm64


Angular: 20.3.16
... common, compiler, compiler-cli, core, forms
... platform-browser, platform-server, router

Package                      Version
------------------------------------
@angular-devkit/architect    0.2003.14
@angular-devkit/core         20.3.14
@angular-devkit/schematics   20.3.14
@angular/build               20.3.14
@angular/cli                 20.3.14
@angular/ssr                 20.3.14
@schematics/angular          20.3.14
rxjs                         7.8.2
typescript                   5.9.3

Anything else relevant?

During creation of a reproduction project, I also noticed, that prerendered routes also do not work with just the CSP token method.

I think the token method is incompatible with the current SSR workflow.
This should probably be documented in the security docs

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: docsRelated to the documentation

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions