Skip to content
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

import maps CSP #2172

Closed
1 of 8 tasks
khangiskhan opened this issue Apr 10, 2020 · 12 comments
Closed
1 of 8 tasks

import maps CSP #2172

khangiskhan opened this issue Apr 10, 2020 · 12 comments

Comments

@khangiskhan
Copy link

  • SystemJS Version:
  • Which library are you using?
    • SystemJS
    • SJS
  • Which extras are you using?
    • AMD extra
    • Named Exports
    • Named Register
    • Transform
    • Use Default
    • Global
  • Are you using any custom hooks?

Question

I need help understanding CSP security restrictions around using SystemJS import maps.

It's noted in the spec that import maps should follow CSP restrictions: WICG/import-maps#105

See Chromium implementation: https://code.immersaview.com/remotes/chromium-third_party/commit/6645330388670d26fb4e22bc9bff38f346151656?w=1

An example in SystemJS is inline import maps:

<script type="systemjs-importmap" nonce="abc">
{
  "imports": {
    "foo": "/foo.js"
  }
}
</script>

<script type="text/javascript" nonce="abc">
System.import('foo');
</script>

The nonce in the import map is ignored. From what I understand, this would allow an attacker to inject their own import map which could change the behavior of imports.

If this is a security hole? What are the avenues to secure it?

@guybedford
Copy link
Member

SystemJS very much respects CSP in that only those scripts permitted to be loaded by the CSP policy can be loaded by SystemJS - this is the reason for the System.register wrapper that is loaded via a global System object and <script> tag instead of fetch+eval execution by default.

Yes, import maps are treated as CSP-level execution in that they can "direct execution" for module trees, but SystemJS does not itself implement CSP policies to restrict import map loading.

But ultimately the capability to run a given top-level execution still comes down to script-src.

By focusing on securing which script-src CSP settings correctly provide the needed restrictions you can secure your site just as with tranditional scripts.

@joeldenning
Copy link
Collaborator

Another thing to consider with CSP is that you likely will need script-src: 'unsafe-inline' in order for SystemJS to access the <script type="systemjs-importmap">. Also here's a link to a comment where @filoxo set up a CSP for a SystemJS application and walked through his reasoning for what he chose: single-spa/create-single-spa#44 (comment)

@guybedford
Copy link
Member

guybedford commented Apr 11, 2020 via email

@joeldenning
Copy link
Collaborator

Code Sandbox

The code sandbox above shows that the script-src must contain both unsafe-inline and unsafe-eval in order for SystemJS to work correctly.

@guybedford
Copy link
Member

@joeldenning that's just because of the <script> tag for the System.import which can be governed by a nonce if necessary. See eg https://codesandbox.io/s/reverent-frog-8cflb?file=/index.html.

@khangiskhan I hope this discussion has answered your query, I'm closing this issue but am happy to continue this thread.

@khangiskhan
Copy link
Author

@guybedford @joeldenning, I can confirm that unsafe-inline for the systemjs-importmap is not necessary, since browsers do not process it for CSP rules.

SystemJS very much respects CSP in that only those scripts permitted to be loaded by the CSP policy can be loaded by SystemJS - this is the reason for the System.register wrapper that is loaded via a global System object and <script> tag instead of fetch+eval execution by default.

Yes, import maps are treated as CSP-level execution in that they can "direct execution" for module trees, but SystemJS does not itself implement CSP policies to restrict import map loading.

But ultimately the capability to run a given top-level execution still comes down to script-src.

By focusing on securing which script-src CSP settings correctly provide the needed restrictions you can secure your site just as with tranditional scripts.

I think I follow your reason why it's not a security hole (as long as you follow CSP settings for scripts), however, I then question what is the rationale for the spec requiring CSP for native browser import-map?

@guybedford
Copy link
Member

however, I then question what is the rationale for the spec requiring CSP for native browser import-map?

The theory is that being able to redirect execution is a vector for injection. In theory access to the import map + ability to write JS scripts is equivalent to the ability to inject <script> tags, so in that sense it might be a unique vector that is different to the current situation.

But the real lock down there would be supporting eg integrity in SystemJS import map parsing. It could certainly be a security extension for those who are genuinely concerned about this attack vector.

@khangiskhan
Copy link
Author

however, I then question what is the rationale for the spec requiring CSP for native browser import-map?

The theory is that being able to redirect execution is a vector for injection. In theory access to the import map + ability to write JS scripts is equivalent to the ability to inject <script> tags, so in that sense it might be a unique vector that is different to the current situation.

I may be missing a key detail here, I am not following how it is different from the situation discussed above. For clarity, the current situation is that we have proper CSP settings, so that no additional CSP protections are required for the systemjs-import script itself.

If I follow your reasoning in your first reply, even for native browser import maps, in the absence of CSP support for type="importmap" (hypothetically), you could still have proper security as long as CSP restrictions are in place for module scripts. The primary point being, even if an attacker can modify an import map (or inject one), the URLs for the modules can be governed by CSP restrictions.

But the real lock down there would be supporting eg integrity in SystemJS import map parsing. It could certainly be a security extension for those who are genuinely concerned about this attack vector.

Are you saying this is just an added layer of protection that could protect against unknown attack vectors, but with current understanding, is not required for minimum security requirements?

Sorry if I may be missing something obvious!

@joeldenning
Copy link
Collaborator

joeldenning commented Apr 15, 2020

Are you saying this is just an added layer of protection that could protect against unknown attack vectors, but with current understanding, is not required for minimum security requirements?

CSP provides guarantees that scripts (and other things) will only ever be downloaded and executed from certain domains / urls. Subresource integrity (SRI) is a separate security mechanism that provides guarantees that the content of downloaded files has not been modified by an attacker. The content could be modified either by the server itself being compromised or by a man-in-the-middle attack that somehow changes the content of the file before it hits the browser (especially relevant if not https). The MDN article I linked to above provides more information about how SRI helps.

The import maps spec does not support SRI. Within SystemJS, SRI currently can be implemented via the createScript hook. However, no official systemjs extension exists for it yet. Guy's comment was saying that we'd be willing to add an official systemjs extension for it if there are people genuinely concerned with that attack vector.

Here are some other relevant links you can take a look at - https://github.com/WICG/import-maps#supplying-out-of-band-metadata-for-each-module and #1953

@guybedford
Copy link
Member

SystemJS now supports an "integrity" property in the import map. This is superior to using a nonce.

@Paramesh-C
Copy link

Is there any documentation on how to add the integrity property to the System.import(<resource_url>) ?

@joeldenning
Copy link
Collaborator

@Paramesh-C as far as I know, the script integrity must be part of an import map - you can't specify it during System.import()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants