【问题标题】:How do I safely run a jq command with a | (pipe) character? [duplicate]如何使用 | 安全地运行 jq 命令? (管道)字符? [复制]
【发布时间】:2021-01-25 17:49:08
【问题描述】:

我有一个程序可以让用户使用 jq 解析 JSON 数据。我选择使用 jq 而不是使用库,因为我发现的那些行为怪异且不一致。我遇到的问题是 jq 通常有 | (管道)字符,这可能会让用户运行非 jq 命令。例如:

jq . | rm file.txt

我如何安全地让用户运行它?

现在,我在 Go 中这样调用它(其中 file.txt 包含原始 json):

cmd = exec.Command("bash", "-c", fmt.Sprintf("cat file.txt | %s", cmd))

谢谢!

编辑: 正如多次指出的那样,这个问题与管道命令无关。它是关于如何安全地执行其中包含管道的 jq 命令。我不希望用户这样做: curl 'api.icndb.com/jokes/random/3' | jq -r '.value[] | .笑话 | rm 文件.txt'。请重新打开。

【问题讨论】:

  • 您需要正确引用传递给 jq 的任何内容。您究竟是如何调用jq 的?您如何处理用户字符串?细节很重要。
  • 哦,好的。我已经编辑了,但如果有更好的方法请提出建议!
  • 好的。在这种情况下,反引号可以用双引号代替。我没有标记为 Go,因为答案不一定是 Go...我感兴趣的部分是我应该运行的命令行命令。
  • 为什么不能使用 go 标准库中的 golang.org/pkg/encoding/json 包?
  • cat is useless. 我猜你是用它作为占位符,但如果你能完全避免调用 shell,你可以大大简化问题。

标签: json linux bash go jq


【解决方案1】:

您可以使用 io.Pipe(),它基本上创建了一个同步的内存管道,它可以用于连接期望 io.Reader 的代码和期望 io.Writer 的代码。例如,如果您有这样的 json 内容:

{
  "fruits": [
    "apples",
    "oranges",
    "pears"
  ]
}

你可以试试这样的:

package main

import (
    "bytes"
    "io"
    "os"
    "os/exec"
)

func main() {
    c1 := exec.Command("cat", "/home/fruits.json")
    c2 := exec.Command("jq", ".fruits[0:2]")

    r, w := io.Pipe()
    c1.Stdout = w
    c2.Stdin = r

    var b2 bytes.Buffer
    c2.Stdout = &b2

    c1.Start()
    c2.Start()
    c1.Wait()
    w.Close()
    c2.Wait()
    io.Copy(os.Stdout, &b2)
}

它会给你这样的东西:

[
  "apples",
  "oranges"
]

即使您可以像这样通过管道传输多个命令,我还是强烈建议您使用标准库中的 json 包到 Marshal 和 Unmarshal JSON。

【讨论】:

  • 问题是如何安全地做到这一点。这可能会导致问题: curl 'api.icndb.com/jokes/random/3' | jq -r '.value[] | .笑话 | rm 文件.txt'
  • @user_78361084,不,它不能(*),因为上面的代码中没有涉及到shell。 jq 的参数仅由 jq 本身解释,没有别的。 * 这是假设您不让客户端控制文件名。
猜你喜欢
  • 2012-12-27
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2013-09-13
  • 2012-07-28
  • 2011-04-25
相关资源
最近更新 更多