Javascript CSP:如何允许给定 URI 前缀的不安全评估 (Firefox)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10944794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CSP: How to allow unsafe-eval for a given URI prefix (Firefox)
提问by Mikko Rantalainen
I'm trying to use MathJaxas part of our web application which uses pretty strict Content Security Policy (CSP). The problem is that MathJax is coded to use eval()
[to be exact, in form of Function()
] which is not considered safe by default by CSP.
我正在尝试使用MathJax作为我们使用非常严格的内容安全策略 (CSP) 的Web 应用程序的一部分。问题是 MathJax 被编码为使用eval()
[确切地说,以Function()
] 的形式,CSP 默认情况下认为这是不安全的。
I'm using following CSP header currently:
我目前正在使用以下 CSP 标头:
X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation';
Which causes MathJax 2.0 code to fail because it uses Function()
. I tried to allow unsafe-eval (i.e. Function()
) only for MathJax located within the same origin below path /:static/math/
. To do that, I tried to add
这会导致 MathJax 2.0 代码失败,因为它使用Function()
. 我试图只允许 unsafe-eval(即Function()
)用于位于 path 下相同原点的 MathJax /:static/math/
。为此,我尝试添加
unsafe-eval '/:static/math/*'
to make the full header look like
使完整的标题看起来像
X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation'; unsafe-eval '/:static/math/*'
but I still cannot Firefox 13.0 to run the code. I'm getting an error message to Firefox Web Console (located in Tools - Web Developer):
但我仍然无法在 Firefox 13.0 上运行代码。我收到一条到 Firefox Web 控制台的错误消息(位于工具 - Web 开发人员):
[10:09:59.072] call to Function() blocked by CSP @ http://localhost:8080/:static/math/2.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML:29
However, I'm not getting a CSP report to the 'report-uri'. (As you see, I'm currently running the test through custom localhost port without SSL, in case that makes a difference. The colon before static
is not a typo, I'm reserving all path parts starting with a colon for internal use of the application, all user content may freely define other URLs.)
但是,我没有收到“report-uri”的 CSP 报告。(如您所见,我目前正在通过没有 SSL 的自定义本地主机端口运行测试,以防有所不同。前面的冒号static
不是错字,我保留所有以冒号开头的路径部分供内部使用应用程序,所有用户内容都可以自由定义其他 URL。)
Is my use of unsafe-eval
attribute incorrect or is it impossible to allow unsafe-eval only for subset of 'self'?The intent is to allow unsafe-eval only for same origin path prefix /:static/math
, strict CSP JS code execution for 'self
' and no JS code for any other method.
我对unsafe-eval
属性的使用是不正确还是不可能只允许对“自我”的子集进行不安全评估?目的是允许 unsafe-eval 仅用于相同的原始路径前缀/:static/math
,对 ' self
'执行严格的 CSP JS 代码,并且没有任何其他方法的 JS 代码。
采纳答案by Mikko Rantalainen
There're multiple issues:
有多个问题:
The
Content-Security-Policy
(CSP) header does not work this way. CSP only has granularity of a single host+port combination (origin). If you cannot allow all scripts to haveunsafe-eval
, no script can have it. The only possible workaround is to not use a script that requiresunsafe-eval
(fortunately, MathJax no longer requiresunsafe-eval
since MathJax bug 256was fixed).The
allow
syntax is an old Mozilla variant and should not be used. The current syntax is to saydefault-src
followed by scheme or host names or origins that are allowed as source of everything and then override the default value for each sub type (e.g.script-src
) as needed. Some sources may support additional source keywords in addition toself
. For example, thescript-src
supportsunsafe-eval
which means that any script that is otherwise allowed to execute is allowed to run eval() or Function(), andunsafe-inline
meaning that any piece of markup that can support some kind of inline script is allowed to execute. Allowingunsafe-eval
may be acceptable butunsafe-inline
is pretty much no-go with script-src (otherwise, you should not bother with the CSP at all).The correct syntax for
script-src
as follows:script-src 'self' cdnjs.cloudflare.com
combined with loading MathJax from https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js
MathJax also uses inline style attributes so following is needed (unless already allowed) or MathJax will raise
Exception
while trying to render the math:style-src 'self' 'unsafe-inline'
It is not possible to use CSP to allow JS to insert style attributes and not have style attributes already inserted in the HTML source to have an effect.
It seems that Firefox 13.0 (at least) does not immediately "call home" in case of CSP violation. Most of the violation reports do get submitted some time after the event. Chrome seems to be much more aggressive with the report submission which will make it a bit easier to test. From my experience, Firefox does not always send CSP report at all - it may be using some kind of heuristic to not send repeated messages.
该
Content-Security-Policy
(CSP)头不以这种方式工作。CSP 只有单个主机+端口组合(源)的粒度。如果您不能允许所有脚本都拥有unsafe-eval
,那么没有脚本可以拥有它。唯一可能的解决方法是不使用需要的脚本unsafe-eval
(幸运的是,MathJax 不再需要,unsafe-eval
因为MathJax 错误 256已修复)。该
allow
语法是旧的 Mozilla 变体,不应使用。当前的语法是说default-src
后跟方案或主机名或允许作为一切来源的来源,然后script-src
根据需要覆盖每个子类型(例如)的默认值。除了self
. 例如,script-src
支持unsafe-eval
意味着允许以其他方式执行的任何脚本都允许运行 eval() 或 Function(),这意味着允许执行unsafe-inline
任何可以支持某种内联脚本的标记。允许unsafe-eval
可能是可以接受的,但unsafe-inline
对于 script-src 来说几乎是不可能的(否则,你根本不应该打扰 CSP)。正确的语法
script-src
如下:script-src 'self' cdnjs.cloudflare.com
结合从https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js加载 MathJax
MathJax 还使用内联样式属性,因此需要以下(除非已经允许)否则 MathJax 将
Exception
在尝试呈现数学时引发:style-src 'self' 'unsafe-inline'
不可能使用CSP来让JS插入样式属性而不是已经在HTML源中插入样式属性来生效。
在违反 CSP 的情况下,Firefox 13.0(至少)似乎不会立即“回电”。大多数违规报告确实会在事件发生一段时间后提交。Chrome 似乎更积极地提交报告,这将使它更容易测试。根据我的经验,Firefox 并不总是发送 CSP 报告 - 它可能使用某种启发式方法来不发送重复消息。
In the end, to make MathJax work with Content-Security-Protection, you need following headers (assuming you're using MathJax via CDNJS):
最后,为了使 MathJax 与 Content-Security-Protection 一起工作,您需要以下标头(假设您通过 CDNJS 使用 MathJax):
Content-Security-Policy: default-src 'self'; script-src 'self' cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline';
Older browsers (e.g. Firefox 13) used to require extra parameters such as options
or required using non-standard headere name such as X-Content-Security-Policy
or X-WebKit-CSP
. These hacks are no longer required because user agents support standard header nowadays. (With the exception of MSIE in contrary to MS Edge.)
较旧的浏览器(例如 Firefox 13)过去常常需要额外的参数,例如options
或 required 使用非标准标题名称,例如X-Content-Security-Policy
或X-WebKit-CSP
。不再需要这些 hack,因为现在用户代理支持标准标题。(MSIE 与 MS Edge 不同。)