我正在开发一个 Java 项目。在其中,我们希望最终用户能够定义基于一组给定的原始类型或字符串变量计算的变量。在某些时候,所有给定的变量都设置为特定的值,然后应该进行计算。然后必须将所有生成的计算变量发送到 Java。
我正在评估最终用户定义其计算的方法。(当前)想法是让他编写 JavaScript 并让该代码在 Java 程序中解释/执行。我知道有两种方法可以做到这一点:使用 javax.scripting API 或 GraalVM/Truffle。在这两种情况下,我们都会这样做:
- 给定的变量被赋予到脚本中。在 javax.scripting 中
ScriptEngine.put
,在 Graal/Truffle 中,通过Value.putMember
. - 最终用户可以在全局上下文中定义变量(其名称不得与来自 Java 的名称冲突)。他如何设置它们的值取决于他 - 他可以直接设置它们(到一个常数,到给定变量之一,到其中一些的总和......)或定义对象和函数并通过调用这些来设置值.
- 当给定变量具有固定值时,将执行脚本。
- 脚本在全局上下文中定义的所有变量都将发送到 Java。在 javax.scripting 中
ScriptEngine.get
,在 Graal/Truffle 中,通过Value.getMember
.
注意:我们不会授予脚本访问任何 Java 类或方法的权限。在 javax.scripting 中通过检查脚本是否包含字符串Java.type
(并禁止这样的脚本),在 Graal/Truffle 中通过使用默认值Context
(具有allowAllAccess=false
)。
互联网上充满了关于 JavaScript 安全问题以及如何避免它们的提示和技巧。一方面,我觉得它们都不适用于这里(解释如下)。另一方面,我不太了解 JavaScript——除了纯粹的、无副作用的计算,我从未将它用于其他任何事情。
所以我在这里寻找一些指导:在这种情况下可能会出现什么样的安全问题?
为什么在这种情况下我看不到任何安全问题:
这是纯 JavaScript。它甚至不允许创建可用于例如在磁盘上创建文件的 Blob(它是 WebAPI 的一部分,而不是 JavaScript)。我知道 JavaScript 不包含任何逃避其沙箱的功能(如文件访问、线程、流......),它仅能够操纵提供给其沙箱的数据。请参阅https://262.ecma-international.org/11.0/#sec-overview的这一部分:
ECMAScript 是一种面向对象的编程语言,用于在主机环境中执行计算和操作计算对象。此处定义的 ECMAScript 并非旨在实现计算自给自足;实际上,本规范中没有规定外部数据的输入或计算结果的输出。相反,预计 ECMAScript 程序的计算环境将不仅提供本规范中描述的对象和其他设施,还提供某些特定于环境的对象,其描述和行为超出了本规范的范围,除非指出它们可以提供可以访问的某些属性和可以从 ECMAScript 程序调用的某些函数。
我们场景中的沙箱只放入了一些无害的玩具(即给定的原始类型或字符串的变量),在孩子玩过它们(脚本已运行)后,生成的建筑物(用户定义的变量)被拿走出来保存它们(在Java程序中使用)。