paragonie / csp-builder

Build Content-Security-Policy headers from a JSON file (or build them programmatically)
https://paragonie.com/projects
MIT License
544 stars 39 forks source link

Calling disableOldBrowserSupport can lead to un-expected regressions with frame-src directives #75

Open fredericgboutin-yapla opened 9 months ago

fredericgboutin-yapla commented 9 months ago

Hi there, First of all, thanks for this great component!

We just had an issue with some frame-src directives that started to "mysteriously disappear". For example, we initialize a builder and we set some global directives,

$cspBuilder = new \ParagonIE\CSPBuilder\CSPBuilder();
$cspBuilder->addSource('frame-src', 'first-frame-src');
$cspBuilder->disableOldBrowserSupport();

And then in the code, we dynamically add some directives, depending on the requirements,

$cspBuilder->addSource('frame-src', 'second-frame-src`);

When the response is about to being sent, we generate the final header and we send it.

The problem is that calling disableOldBrowserSupport() in between 2 different addSource() for frame-src will generate different directives - see https://github.com/paragonie/csp-builder/blob/34b2d80cf751ad39cf9a4d980dbdba05cf2f7cfd/src/CSPBuilder.php#L175

And in that specific scenario, since we define frame-src and child-src first and then child-src only, we end up with the second-frame-src being only defined in the child-src but the browser cannot resolve it since there is a frame-src directive for the first-frame-src

As per Mozilla doc,

If this directive is absent, the user agent will look for the child-src directive (which falls back to the default-src directive).

Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src

As a work around, we moved the disableOldBrowserSupport() call just after creating the builder and it works but I think that it should be a constructor's option instead so you cannot just change the addSource() behavior in the middle of the CSP builder usage, screwing up the following frame-src directives.