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 · 41 comments

Comments

Projects
None yet
@mikkorantalainen
Copy link

commented Jun 11, 2012

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

This comment has been minimized.

Copy link

commented Jul 9, 2012

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

This comment has been minimized.

Copy link

commented Jul 16, 2012

+1

@pkra

This comment has been minimized.

Copy link
Member

commented Jul 16, 2012

Thanks guys. We'll look into it.

@pkra

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

commented Jul 17, 2012

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

This comment has been minimized.

Copy link

commented Jul 17, 2012

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

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. 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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

commented Sep 24, 2013

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

@pkra

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

commented Sep 25, 2013

+1 for complying with CSP.

@knuton

This comment has been minimized.

Copy link

commented Oct 3, 2013

+1

@matteius

This comment has been minimized.

Copy link

commented Oct 31, 2013

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Member

commented Nov 30, 2013

Thanks @ketch , that's good to know.

@pkra

This comment has been minimized.

Copy link
Member

commented Dec 10, 2013

@dpvc should we add this to the next milestone?

@khughitt

This comment has been minimized.

Copy link

commented Dec 10, 2013

👍

@dpvc

This comment has been minimized.

Copy link
Member

commented Dec 10, 2013

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

@pkra

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

commented Dec 13, 2013

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

@emichael

This comment has been minimized.

Copy link

commented Mar 17, 2014

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

commented Mar 18, 2014

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Member

commented Mar 18, 2014

OK, I've made a patch that removes the new Function() and eval() calls. It is based off the latest development branch, but the changes listed in f220993 should be able to be made to the master copy of MathJax.js as well, if you need to do that. You do need to allow in-line styles (there is really no getting around that). There is also a font reference to about:blank so that MathJax can test the response to a missing font (without having to make a network access), so you might want to add about: to font-src as well. Once I changed those two, this copy of MathJax ran without a hitch.

@emichael

This comment has been minimized.

Copy link

commented Mar 19, 2014

Nice! I can see why you definitely need 'unsafe-inline' for styles.

As far as the script-src 'unsafe-inline' permission goes, if I understand you correctly, scripts are only ever in-lined when the user includes inline MathJax configuration to start with. This would be fine, since everything could still work without 'unsafe-inline' in script-src. It should be mentioned in the docs, though.

@dpvc

This comment has been minimized.

Copy link
Member

commented Mar 19, 2014

Your understanding about inline scripts is correct. You do not need script-src 'unsafe-inline' unless you are using in-line configuration blocks, which you don't need to use. You can use either a local MathJax configuration file (added to the config=) or you can use a normal script file that sets the MathJax variable to an object that you would normally pass to MathJax.Hub.Config() and load that file before your script that loads MathJax.js. For example, put

var MathJax = {
  tex2jax: {
    inlineMath: [['$','$'],['\\(','\\)']],
    procesEscapes: true
  }
};

into a file called mathjax-config.js and then

<script src="mathjax-config.js"></script>
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>

I hope that that takes care of your requirements.

@emichael

This comment has been minimized.

Copy link

commented Mar 19, 2014

It does indeed. Thanks for the quick fix!!

@dpvc

This comment has been minimized.

Copy link
Member

commented Mar 19, 2014

There are some here who would say it was not all that fast (the issue has been open for two years!), but I did have it marked for the next release, and was just getting down to it anyway, so your comment came at the appropriate time.

@dpvc

This comment has been minimized.

Copy link
Member

commented Mar 20, 2014

=> Merged.

@silky

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Sep 11, 2014

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

commented Sep 13, 2014

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

@pkra

This comment has been minimized.

Copy link
Member

commented Sep 15, 2014

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

@kaushalmodi

This comment has been minimized.

Copy link

commented Apr 27, 2018

I am still seeing this issue. See #1988.

@dpvc

This comment has been minimized.

Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.