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

MathJax requires unsafe "Content Security Policy" #256

Closed
mikkorantalainen opened this issue Jun 11, 2012 · 44 comments
Closed

MathJax requires unsafe "Content Security Policy" #256

mikkorantalainen opened this issue Jun 11, 2012 · 44 comments
Labels
Accepted Issue has been reproduced by MathJax team Fixed Test Not Needed v2.4
Milestone

Comments

@mikkorantalainen
Copy link

The current MathJax implementation uses following features that are not considered safe in modern world and cannot be used with default Content-Security-Policy (http://www.w3.org/TR/CSP/) headers:

  • JavaScript evaluation of strings (new Function() with a string or eval()) (1)
  • Inline style attributes inserted via JavaScript (2)

It's debatable if issue (2) should be fixed but at least (1) should be fixed because Content-Security-Policy does not have enough granularity to allow MathJax to execute as a trusted script and in the same time do not interpret every other JavaScript file as specially trusted. Currently, if one wants to use MathJax, he must allow eval() everywhere. The issue (1) also causes bug #130 (MathJax is incompatible with ECMAScript 5 strict mode).

Currently the only way to make MathJax to work, even if one uses locally installed MathJax code, is to use following CSP HTTP headers (the deprecated "options" header is included for Firefox 13.0 and lesser):

X-Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; options eval-script
X-WebKit-CSP: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'

These headers will allow some CSP provided protection and still allow MathJax to work, if MathJax is distributed from the same origin as the page content.

@matthewrobertson
Copy link

unsafe eval is a big issue for me as well. Very soon chrome will force all extensions to adopt a content security policy that bans the use of eval. We are currently trying to upgrade Readium to comply with this but we cannot use do so and use MathJax

@gcapiel
Copy link

gcapiel commented Jul 16, 2012

+1

@pkra
Copy link
Contributor

pkra commented Jul 16, 2012

Thanks guys. We'll look into it.

@pkra
Copy link
Contributor

pkra commented Jul 17, 2012

Just a preliminary update. It seems possible to fix some of the issues soon enough (hopefully enough for the Chrome store). However, we're not sure how the performance will suffer -- which, as you can guess, could be bad. We'll keep you updated when @dpvc can look at this in more detail and perhaps create some experimental branches.

If you have additional comments, questions and suggestions about specific code, please let us know.

@matthewrobertson
Copy link

I spent a bit of time looking into it myself. It seems like you guys need to stop with the premature optimization. Evaling a string is NOT faster than creating a closure.

@matthewrobertson
Copy link

Also, you shouldn't be running eval() on every page that loads Mathjax just to check if you can run eval(). Basically, this needs to go.

@dpvc
Copy link
Member

dpvc commented Jul 18, 2012

The new Function() calls are not for speed but for memory. The new Function() doesn't create a closure, and so doesn't hold onto the local scope. Since this is at the heart of the object-oriented programming model, and there are lots of objects in use, it could have an impact on memory usage. I haven't done any testing of that in recent browsers.

As for eval usage, MathJax does use it to handle its in-line configuration blocks, and that could not be easily replaced at this point. So a "safe" version of MathJax would need to use external configuration files (which should not be a problem, and probably is more in line with the security policy anyway). The eval call you refer to is not to determine if eval can be run, but to determine if it runs in the global namespace (which isn't the case in all browsers). I'm aware that this would need to be removed for a version that would work with your security needs.

@matthewrobertson
Copy link

That is not how closures work in javascript. You do not hold on to everything in local scope; you only capture things that your function uses. Your CONSTRUCTOR function uses nothing from the local scope there is no cost to creating the closure. This is premature optimization for a problem that never existed.

As far as the eval thing is concerned my point is that you should not be running code on a page if you don't need to, especially if that code that uses unsafe eval(). You only use that EVAL function if Mathjax has been included with in-line configuration so, don't run the test for it until you need to. But really, why on earth does the configuration have to be executable code. It is really just a chunk of JSON that is passed to function. Why not just pass the JSON, parse it and have MathJAX call the function?

@dpvc
Copy link
Member

dpvc commented Jul 18, 2012

That is not how closures work in javascript. You do not hold on to everything in local scope; you only capture things that your function uses.

I don't think things are as clear cut as that. First, this was not the case back in 2008 when that part of the code was written. I have just run tests this morning that appear to confirm that the versions of Safari, Firefox, Opera, and IE in play at the time all worked the way I described (the complete scope chain was retained in a closure, regardless of the variables used). The site that is my reference for this seems to be down this morning (was up yesterday), so I can't check details, but my recollection is that this was part of the ECMAScript 262 specification.

Current versions of Safari, Chrome, Firefox, and IE do appear to work as you describe, so somewhere since then things have changed. It looks like Safari 4, Firefox 3.6, and IE9 were where the change occurred; I don't have old versions of Chrome to test, so don't know the history there. IE8 has the older behavior, and Opera 12 still does. I have not checked mobile devices. Some of these browsers are on MathJax's support list, so it is still an issue that we have to consider for MathJax in general. Of course, I'm sure something can be worked out for your needs.

As for JSON data, the configuration block may be more than just a MathJax.Hub.Config() call. For example, you can install event listeners, or add functions to the TeX input jax to implement additional commands, and so on. These can't be part of JSON data because they include executable code. This feature is not always used, but it certainly is being used by actual web sites. In addition, not all the target browsers have a JSON library built in, and so there would need to be additional libraries to do the parsing. (Certainly not insurmountable, but more code to download.)

@ketch
Copy link

ketch commented Sep 24, 2013

+1 for changing this, so that (among other things) Github will allow MathJax in their wikis again.

@pkra
Copy link
Contributor

pkra commented Sep 24, 2013

@ketch do you have a reference for Github making a statement in this regard? I don't see how this issue touches Github Wiki security.

@ketch
Copy link

ketch commented Sep 24, 2013

@pkra I don't know for certain that this is the cause, but I believe it to be so. I was led to this by the comments on this page:

http://stackoverflow.com/questions/16889421/how-to-insert-javascript-to-enable-mathjax-on-github-wiki-pages

And see

https://github.com/blog/1477-content-security-policy

I believe MathJax support disappeared at the same time that they implemented the CSP feature.

@pkra
Copy link
Contributor

pkra commented Sep 24, 2013

Thanks, that's interesting. I'm not sure the two are related but who knows -- the github team never publicly discussed why they removed MathJax. It would be unfortunate if something that's actually a non-issue for their setup would have been the reason.

@tss
Copy link

tss commented Sep 25, 2013

+1 for complying with CSP.

@knuton
Copy link

knuton commented Oct 3, 2013

+1

@matteius
Copy link

I read this thread and found it very informational and fairly unbiased. I am going to stake my claim that they [github] would prevent something like exec, CSP on the matters of security and not allowing it.

Besides being mystified by that code sample and your mythic computer lore of past versions, I find it very interesting none the less and take the position of that a feature should be made available for its continued use, though it shouldn't interfere with the happy path of using MathJAX in security concerned world.

@ketch
Copy link

ketch commented Nov 29, 2013

By the way, I e-mailed Github support about why they dropped MathJax. Here is the reply:

CSP was one of the reasons. Other reasons included performance issues, and hard maintenance. We might consider adding it back if we eliminated the reasons that lead us to remove it, but I can't promise that.

@pkra
Copy link
Contributor

pkra commented Nov 30, 2013

Thanks @ketch , that's good to know.

@pkra
Copy link
Contributor

pkra commented Dec 10, 2013

@dpvc should we add this to the next milestone?

@khughitt
Copy link

👍

@dpvc
Copy link
Member

dpvc commented Dec 10, 2013

@pkra, I was planning to add it. Just hadn't gotten this far down numerically in the list yet.

@pkra
Copy link
Contributor

pkra commented Dec 10, 2013

@dpvc right. I was mostly wondering if fixing this would require significant changes (especially wrt inline configurations), i.e., force a version jump.

@dpvc
Copy link
Member

dpvc commented Dec 10, 2013

The changes we made to allow configuration via the MathJax variable should make it possible to include it without a jump. I'm pretty sure I can do it with backward compatibility and without having to make a separate "safe" version of MathJax.js. Of course, something could show up during the development that would throw a monkey wrench into the works; none of it is written or tested yet.

@salomons
Copy link

+1 for making MathJax secure. Too bad not being able to use this nice library in production due to the security concerns.

@emichael
Copy link

Any progress on this issue? I'm trying to programatically inject MathJax into pages with a Chrome extension, and I'm hitting if not a brick wall at least a decently solid wall. As described in emichael/texthings#4, my biggest problem now is with MathJax.js:265. I was able to eliminate the calls to

new Function()

pretty easily by turning them into closures as described above, but I have no clue how to get around using eval or an inline script.

EDIT: I ended up giving the user an option to add unsafe-eval and unsafe-inline to the CSP, but a long-term fix to get MathJax to a safe CSP would be nice. 👍

@dpvc
Copy link
Member

dpvc commented Mar 18, 2014

@emichael, we are planning to include the changes in the next release (planned for next month), but I haven't made them yet. One reason is that I haven't looked into how you actually test this (how to set up the environment that requires it). If you could give me a suggestion of where to look or what a minimal testing environment might be, that would help.

Also, is the error about eval one that occurs at run time or at compile time? That is, does it occur if MathJax.js simply includes an eval call, even if it is never used, or does it happen only when eval actually is attempted? My reading of the spec suggests that it should be a run-time error, which would make things better for me, but I thought you might know the answer.

@emichael
Copy link

If you have a test server, you can just set Content-Security-Policy in the response headers. Just make sure that script-src doesn't include 'unsafe-eval' or 'unsafe-inline' (GitHub itself is a good example). If you don't, you can use a very minimal Chrome extension to inject the headers yourself.

It's a runtime error.

@dpvc
Copy link
Member

dpvc commented Mar 18, 2014

Thanks. I'll see what I can do.

The eval command is only used to process the in-line configuration blocks (and there is an initial one to test how global variables are handled in that case). The initial one can be put off until an inline configuration is used, and if you avoid using in-line configuration, then that should take care of it. In v2.3 we added a new way of doing in-line configuration without eval (in preparation for resolving this issue), so you can still include MathJax configuration within the HTML files without triggering the eval call.

@dpvc
Copy link
Member

dpvc commented Mar 20, 2014

=> Merged.

@silky
Copy link

silky commented Jun 6, 2014

so has anyone asked github to allow mathjax yet? it's still not possible to write a dotjs file that lets me write tex in github issues so-as to render with mathjax...

(the example here - http://stackoverflow.com/questions/16889421/how-to-insert-javascript-to-enable-mathjax-on-github-wiki-pages - fails.)

bvancil referenced this issue in kubetz/mathjax-bookmarklet Jun 19, 2014
@dpvc dpvc added v2.4 and removed Merged labels Jun 30, 2014
@diego898
Copy link

Hello,

I am currently hosting a jekyll site on github pages and following this article, and have added the following to my includes file:

<script type="text/javascript"
  src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

Which is supposed to work with https or http. However, when loading my blog on a browser with https everywhere it looks messed up until you click to allow unsafe script. How can I fix this?

@pkra
Copy link
Contributor

pkra commented Sep 13, 2014

@silky nothing specific AFAWK. Client-side is unlikely, I think, but MathJax-node could provide a productive alternative.

@diego898 General questions fit better at http://groups.google.com/forum/#!forum/mathjax-users; always include a link to a live page, browser and OS specifics etc. Thanks.

@diego898
Copy link

@pkra I understand I just wasnt sure if it was bug related to this issue, or a configuration issue on my part

@pkra
Copy link
Contributor

pkra commented Sep 15, 2014

@diego898 no problem. What you describe does not sound like it's related to this issue.

@kaushalmodi
Copy link

I am still seeing this issue. See #1988.

@dpvc
Copy link
Member

dpvc commented Apr 27, 2018

@kaushalmodi, see my comment above about how to avoid the problem, or my comment to the issue you link to. You have to change how you configure MathJax if you are using a CSP that restricts script execution.

@mkamensky
Copy link

Was (2) in the original issue ever resolved? It seems that mathjax v3 still inserts <style> tags into the head

cmbuckley added a commit to cmbuckley/cmbuckley.github.io that referenced this issue Feb 25, 2022
@scruel
Copy link

scruel commented Mar 10, 2023

For MathJax version 3, the issue still exists.
I am writing Tampermonkey scripts which can't include other script file to load the configuration, also I will get CSP related errors while MathJax loading its fonts.
image

@dpvc
Copy link
Member

dpvc commented Mar 15, 2023

@scruel, you say:

For MathJax version 3, the issue still exists.

Your issue is not the same as either (1) or (2) in the original message. (1) has been resolved in v3 (and could be avoided in v2 by using the MathJax={...} form of configuration). (2) is not going to be something we are able to avoid easily, but there is code in a comment to another issue that may be able to address that using nonces (but read the full thread for some caveats).

To be able to use MathJax with a CSP, you would need to include the CDN from which you obtain MathJax in the font-src and script-src directives (as well as allowing in-line styles). If you are trying to insert MathJax into a page that has a CSP that you don't control, and if the CDN is not included there, then you may not be able to do it.

You may have better luck using the SVG output rather than CHTML, since that doesn't load fonts, only javascript, but if you can't load external javascript files, then that may limit what you are able to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted Issue has been reproduced by MathJax team Fixed Test Not Needed v2.4
Projects
None yet
Development

No branches or pull requests