2024 年 Clojure 调查! 中分享你的想法。

欢迎!请参阅 关于 页面以了解更多关于如何使用此功能的详细信息。

+1 投票
语法和读取器

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

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

但在使用 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 有一个类似的动态 var,clojure.tools.reader/*read-eval*,它以同样的方式使用,因此你需要同时绑定这两个。

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

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

我建议添加适当的文档,因为这并不清楚,可能在我们没有考虑到的位置创建代码执行。
关于 clojure.core/read 和 clojure.core/read-string 这里的文本能说明什么? 这是几年前在将 clojure.edn 命名空间添加到 Clojure 时写的,当时 read 函数有 doesn't-read-code-only-data 的变体,看来对我来说仍然准确:[https://docs.clojure.org/clojure.core/read](https://docs.clojure.org/clojure.core/read)
这里的困惑是否来自于这个文档并没有明确指出它在讨论哪个 *read-eval*?

http://clojure.github.io/tools.reader/#clojure.tools.reader/read-string

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

我也可以理解那些绑定核心变量的人想要它“普遍”应用(即,也可能控制 Contrib 库的行为——假定 Contrib 库属于 Clojure 组织,因此可能有一定的相互依赖性)。
Sean,我觉得这正是我思考并感到困惑的地方。

我看到许多Clojure开发者使用read-string,但并不真正了解其对安全的影響,甚至当尝试通过*read-eval*符号禁用它时都会感到困惑。在这场讨论中,我了解到需要将不同命名空间中的两个绑定放置在一起。

我希望有一个可以放置的绑定,可以确保在那些常用的read-string函数中不会有eval。
一个很好的方法是对开发者进行教育,让他们了解clojure.core/read和clojure.core/read-string的不安全性,例如,指出我提供的链接中的示例。

另一个方法是为他们提供一些你信任的安全函数,并建议他们使用这些函数。评论这些函数或编写长篇大论的文档来说明为什么它们更安全,以及替代方法的哪些部分是不安全的。

提供的现成替代方案是为了让那些使代码更安全的人方便使用。教育仍然是必需的,这样他们才知道这些函数的存在。
...并鼓励他们不要使用tools.reader函数——这是一个常见的传递依赖,所以我可以理解他们在代码库中如何发现它,并认为使用“读取器”命名空间读取字符串是直接、正确的做法。
...