2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请查看 关于页面 了解其工作方式的更多信息。

+1 投票
语法和reader

我是 Clojure 的新手,试图理解该语言的一些安全方面。

在文档中,我了解到将 read-eval 绑定到未知应拒绝代码执行。

但当我用 clojure.core/read-string 下的代码进行测试时,使用 clojure.tools.reader/read-string 它会执行。

我还看到 reader.edn 不会执行代码,但我想确认即使在我们的开发者错误地使用了 clojure.tools.reader 的情况下,也不会执行任何代码

谢谢,Rotem

POC

(binding [*read-eval* :unknown]
(clojure.tools.reader/read-string "#=(* 2 21)"))
=> 42

1 个答案

+1 投票

如果他们“误操作”包含额外的库并调用任意代码,那么他们可以误做任何事情。

clojure.tools.reader 有一个类似的动态变量 clojure.tools.reader/*read-eval*,它以相同的方式使用,因此您需要同时绑定两者。

明白了,我想为测试设置一个 *read-eval* 为 unknown,以验证没有代码正在运行,就像 clojure.core 不需要 clojure.core/*read-eval* 绑定一样

是的,在安全性方面,我要确保开发者知道他们想要eval功能。我建议将其默认设置为false,但这是一个更核心的需求。

我建议添加适当的文档,因为目前并不清晰,可能会在未曾考虑过的地方执行代码。
对于clojure.core/read和clojure.core/read-string的文本,有什么帮助吗?这是在Clojure中添加clojure.edn命名空间、并且添加了只读取数据而不读取代码的read函数变体时写的,看起来对我来说仍然是准确的:[链接](https://docs.clojure.org/clojure.core/read)
这里的困惑是否是因为这个文档没有明确说明所讨论的哪个*read-eval*?

[链接](http://clojure.github.io/tools.reader/#clojure.tools.reader/read-string)

我可以看到,一个人在阅读了核心的read/read-string文档之后,可能会阅读tools.reader的文档,而不会意识到它讨论的是单独的clojure.tools.reader/*read-eval*而不是核心变量。

我也可以看到,为什么将核心变量绑定的人想要它在“普遍”上生效(即,它也可能控制贡献库的行为——假设贡献库属于Clojure组织,因此可能会有一定的依赖性)。
Sean,我认为这正是我的想法和困惑所在。

我看到很多Clojure开发者使用read-string,而实际上并不真正了解其对于安全性的影响。即使尝试通过*read-eval*符号来禁用它,仍然会很迷惑,而我通过这次讨论学到的是需要将不同命名空间的两个绑定分开。

我希望拥有一个绑定,这样我就可以确信在这些常见的read-string函数中不会有eval。
头像
一个合适的方法是教育开发者关于 clojure.core/read 和 clojure.core/read-string 的不安全性,例如指给他们我上面提供的链接中的示例。

另一个方法是为他们提供一组你信任的安全函数,并建议他们使用这些函数。可以对它们进行注释,或写出长长的文档字符串,说明它们为什么更安全,以及替代方案有什么不安全的地方。

现成的替代方案是为了方便那些使他们的代码更加安全的开发者使用。然而,教育仍然需要,使他们意识到这些函数的存在。
头像
...并鼓励他们不要使用 tools.reader 中的函数 —— 它是一个常见的传递依赖项,所以我可以理解他们如何在代码库中找到它,并认为使用 “reader” 命名空间读取字符串是显然的、正确的方式。
...