angular-cli icon indicating copy to clipboard operation
angular-cli copied to clipboard

application builder - strict-dynamic - issues with content security policy

Open joergbaier opened this issue 1 year ago • 2 comments

Command

build

Is this a regression?

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

The previous version in which this bug was not present was

@angular-devkit/build-angular:browser

Description

This is a follow up to https://github.com/angular/angular-cli/issues/26330 and appreciate the work on adding the preloadInitial flag.

It seems like the real issue is the way chunks are loaded by esbuild (screenshots below):

  • webpack created a runtime.js file that loads scripts in a way that worked with strict-dynamic
  • esbuild calls import ... from "chunk.js"; directly from main.js

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#strict-dynamic

The 'strict-dynamic' source expression specifies that the trust explicitly given to a script present in the markup, by accompanying it with a nonce or a hash, shall be propagated to all the scripts loaded by that root script. At the same time, any allowlist or source expressions such as 'self' or 'unsafe-inline' will be ignored.

Based on that documentation I would expect both cases to work. For the esbuild case, we are allowing main.js via sha384, which should then be allowed to import further scripts. Is there something I am missing here?

Minimal Reproduction

@angular-devkit/build-angular:browser output

<script
  src="runtime.123.js"
  type="module"
  crossorigin="anonymous"
  integrity="sha384-123"
></script>
<script
  src="polyfills.123.js"
  type="module"
  crossorigin="anonymous"
  integrity="sha384-123"
></script>
<script
  src="main.123.js"
  type="module"
  crossorigin="anonymous"
  integrity="sha384-123"
></script>

Chrome trace for loading the first chunk webpack


@angular-devkit/build-angular:application output

<script
  src="polyfills-123.js"
  type="module"
  crossorigin="anonymous"
  integrity="123"
></script>
<script
  src="main-123.js"
  type="module"
  crossorigin="anonymous"
  integrity="123"
></script>

Chrome trace for loading the first chunk esbuild

Chrome console error

Refused to load the script '.../chunk-123.js' because it violates the following Content Security Policy directive:
"script-src ... 'sha384-123' 'strict-dynamic'".
Note that 'strict-dynamic' is present, so host-based allowlisting is disabled.
Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

Exception or Error

No response

Your Environment

17.3

Anything else relevant?

No response

joergbaier avatar May 09 '24 21:05 joergbaier

I forgot to mention this fails in Chrome and Firefox, however Safari allows the scripts.

joergbaier avatar May 09 '24 21:05 joergbaier

Relevant reading (will update as I find more)

  • https://github.com/w3c/webappsec/issues/544#issuecomment-1287672480

joergbaier avatar May 10 '24 16:05 joergbaier

This sounds like a browser issue, I'm not sure there's anything actionable for Angular here. AFAICT, the hashes are generated correctly, it's just that strict-dynamic is broken for this particular scenario in Chrome and Firefox. I'd recommend filing issues against those two vendors if they don't already exist and avoiding strict-dynamic until that gets resolved.

If there's something we're generating incorrectly, then we can take a look at fixing that within Angular. But otherwise this seems like more of a problem with those browsers.

dgp1130 avatar Jun 05 '24 17:06 dgp1130

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.