New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSP and HTML Modules #544

Open
dandclark opened this Issue Jan 25, 2019 · 4 comments

Comments

Projects
None yet
4 participants
@dandclark
Copy link

dandclark commented Jan 25, 2019

My colleagues and I on the Microsoft Edge team recently shared a proposal for HTML Modules as an extension of ES6 JavaScript modules. HTML Modules allow for access to declarative content from within a script module. Our Explainer Doc fleshes out this idea.

One developer pointed out that our use of inline scripts in HTML Modules could interact poorly with CSP’s unsafe-inline source expression.

An HTML Module uses inline scripts for two primary purposes: to specify its exports, and to import other modules (script or HTML) that it depends on. The reason that inline scripts in particular are required is that a non-inline module script can be imported from multiple contexts, making its referrer document ambiguous, so it’s not clear how a non-inline script would interact with its referrer to specify exports of HTML content.

An HTML Module’s inline scripts are different from normal scripts in a few ways. Firstly, only type=”module” scripts are allowed, so there’s no synchronous execution during parsing. Secondly, their execution isn’t queued up by the parser as per normal deferred scripts. Instead, they are incorporated into the module graph as the required modules of the HTML Module, similarly to how a script module’s required modules consist of the set of modules requested in its all of its import {…} from “…” statements. As such they are executed only after the entire module dependency graph has been fetched, as part of the module graph evaluation when all the modules in a module graph are executed in order of a depth-first post-order traversal.

So, inline scripts in HTML Modules don’t have the same behavior as normal inline scripts. Another way to think about them is that they are declaratively specified script module imports of the HTML module. Additionally, it's impossible to dynamically inject a script into a module in such a way that it will execute; only scripts that were parsed with the original HTML Module are included in the module graph and executed.

Given the above, we believe that inline script elements included in HTML Modules should be allowed to run even without the presence ‘unsafe-inline’ in a script-src directive.

This decision clearly merits input from the experts. Does anyone in the WG have concerns with this? Are there any dangers here that we are missing?

Also worth noting is that we would propose to have the importing of HTML Modules governed under the script-src directive in the same way that it applies to importing of script modules.

One more question we're considering is whether or not an HTML module (which is a document) applies CSP directives specified in its headers when it is being processed as part of the module graph. We're thinking the answer is no -- that only the "root" document's CSP directives apply -- but we're not sure. On the one hand, if I want to consume a module hosted on a third-party server I shouldn't have to worry about whether the server’s lax CSP policies could compromise the security of my application. On the other hand, it seems unintuitive that a text/html response’s CSP is respected or not based on whether it’s getting pulled in as a module vs. loaded as a top-level document. Feedback on this is welcome as well.

We’ve also been considering the issue here regarding module imports in a nonced inline script, but this seems more applicable to ES6 modules in general with no special consideration needed for HTML Modules.

@annevk

This comment has been minimized.

Copy link
Member

annevk commented Jan 28, 2019

only scripts that were parsed with the original HTML Module are included in the module graph and executed

That's still the same basic problem though, no? If you find some kind of XSS (granted, it's more involved as there's multiple steps) an attacker gets to influence that.

I guess the main question if we see these as subresources that are similar to other subresources, or subresources prone to XSS due to their HTML-y nature.

@annevk

This comment has been minimized.

Copy link
Member

annevk commented Jan 28, 2019

(FWIW, script-src makes sense, and I don't think CSP policies delivered with a module script should apply as they don't for "normal" module scripts either.)

@shhnjk

This comment has been minimized.

Copy link

shhnjk commented Feb 10, 2019

I guess the main question if we see these as subresources that are similar to other subresources, or subresources prone to XSS due to their HTML-y nature.

I think HTML Modules isn't prone to XSS. Because it's not meant to dynamically generate HTML according to user input. Yes, there might be a DOM based XSS depending on inline scripts, but that's same as subresources like JS file.

@arturjanc

This comment has been minimized.

Copy link

arturjanc commented Feb 17, 2019

There is some precedent for this in how HTML imports interacted with CSP. AFAIK they applied the loading document's script-src restrictions to both the original HTML import and to any scripts inside the import. @mikewest do you remember what the original reasoning behind this was?

The main concern here is that HTML is frequently constructed unsafely, with user data interpolated without sufficient escaping; we can hope that HTML modules will be static as @shhnjk says, but there is no reason an application couldn't use user-controlled data when returning the contents of the module, leading to an XSS that wouldn't be subject to CSP, resulting in a security regression. OTOH we can also treat this more similarly to ES modules and assume that, once loaded, the module gets the ability to execute scripts -- I don't think that's necessarily a wrong way to look at this.

No concerns from me when it comes to inheriting the loading document's CSP. One thing to keep in mind in this model is that we should tell developers to always also set a CSP on the HTML module response. An attacker can navigate the victim to it directly so if there's a DOM XSS in a script in the HTML module, it would execute in the context of the hosting origin (which is difference between HTML modules and ES modules / JS subresources); developers would need to have CSP set on such responses even if the policy would normally get ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment