You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang中执行Commix命令异常问题求助

问题:Golang执行Commix工具提前退出的异常分析与解决

现象描述

执行命令 commix -r req.txt --ignore-stdin --batch 时:

  • 在Linux终端和Python(v3.12.3)的subprocess调用中,Commix能正常解析HTTP请求文件并启动命令注入测试
  • 但在Golang(v1.22.2)自定义的OsExec函数中,工具仅输出[info] Parsing HTTP request...就以状态码0退出,无后续测试流程

环境与代码对比

Python 正常执行代码

import subprocess
cmd = "commix -r req.txt --ignore-stdin --batch"
returned_value = subprocess.call(cmd, shell=True)
print(returned_value)

Golang 异常执行代码

func OsExec(command, wd string) (output string) {
    var (
        stdout, stderr string
        outbuf, errbuf bytes.Buffer
        exitCode       int
    )

    cmd := exec.Command("/bin/sh", "-c", command)
    cmd.Dir = wd
    cmd.Env = os.Environ()

    cmd.Stdout = &outbuf
    cmd.Stderr = &errbuf

    err := cmd.Run()

    stdout = outbuf.String()
    stderr = errbuf.String()

    if err != nil {
        log.Printf("Error executing command: %v", err)
        exitCode = getErrorExitCode(err)
    } else {
        exitCode = cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
    }

    if stderr == "" && exitCode != 0 {
        stderr += err.Error()
    }

    output = strings.Join([]string{stdout, stderr, "Exit Status: " + strconv.Itoa(exitCode)}, "\n")
    output = strings.TrimPrefix(output, "\n")
    output = strings.TrimSuffix(output, "\n")

    return output
}

func getErrorExitCode(err error) int {
    if exitError, ok := err.(*exec.ExitError); ok {
        ws := exitError.Sys().(syscall.WaitStatus)
        return ws.ExitStatus()
    }
    return 1
}

临时验证方案

当修改Golang代码,去掉--ignore-stdin参数,同时将cmd.Stdout、cmd.Stderr指向os.Stdout、os.Stderr,并添加cmd.Stdin = os.Stdin后,Commix恢复正常运行。

原因分析

Commix的--ignore-stdin参数并非完全屏蔽所有stdin相关检查:

  • 在终端或Python环境中,子进程默认继承父进程的stdin(处于打开状态),即使没有输入,Commix也能继续执行后续流程
  • 而Golang的exec.Command默认不设置Stdin,导致子进程的stdin处于关闭状态。Commix在解析完请求后,可能因检测到stdin关闭而提前退出,而非触发命令注入测试逻辑

解决方案

在Golang的OsExec函数中,显式为子进程设置Stdin,即使使用--ignore-stdin参数也能正常执行:

修改后的OsExec函数

func OsExec(command, wd string) (output string) {
    var (
        stdout, stderr string
        outbuf, errbuf bytes.Buffer
        exitCode       int
    )

    cmd := exec.Command("/bin/sh", "-c", command)
    cmd.Dir = wd
    cmd.Env = os.Environ()

    cmd.Stdout = &outbuf
    cmd.Stderr = &errbuf
    // 显式设置Stdin为os.Stdin,保持stdin处于打开状态
    cmd.Stdin = os.Stdin

    err := cmd.Run()

    stdout = outbuf.String()
    stderr = errbuf.String()

    if err != nil {
        log.Printf("Error executing command: %v", err)
        exitCode = getErrorExitCode(err)
    } else {
        exitCode = cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
    }

    if stderr == "" && exitCode != 0 {
        stderr += err.Error()
    }

    output = strings.Join([]string{stdout, stderr, "Exit Status: " + strconv.Itoa(exitCode)}, "\n")
    output = strings.TrimPrefix(output, "\n")
    output = strings.TrimSuffix(output, "\n")

    return output
}

func getErrorExitCode(err error) int {
    if exitError, ok := err.(*exec.ExitError); ok {
        ws := exitError.Sys().(syscall.WaitStatus)
        return ws.ExitStatus()
    }
    return 1
}

替代方案(无交互场景)

如果不需要从stdin读取输入,也可以将Stdin设置为io.NopCloser(strings.NewReader("")),模拟一个打开但无内容的stdin:

import "strings"
import "io"

// 在cmd设置中替换为:
cmd.Stdin = io.NopCloser(strings.NewReader(""))

内容的提问来源于stack exchange,提问作者PotatoDeveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 13:02:19