nuclei icon indicating copy to clipboard operation
nuclei copied to clipboard

bug: nuclei execution cannot be started without closing the standard input pipe

Open hktalent opened this issue 6 months ago • 5 comments

describe:

When executing an nuclei command using exec.Command, I discovered that if the standard input pipe wt is not closed, nuclei gets stuck and never starts execution. This prevents streaming and may cause memory overflow issues. This problem does not exist with the tlsx command.

Steps to reproduce:

  • Use exec.Command to execute the nuclei command and get the standard input pipe wt.
  • Write data to wt without closing wt.
  • Wait for nuclei to execute and output the results.

Expected behavior:

Even if the standard input pipe wt is not closed, nuclei should be able to start execution and process the input stream.

Actual behavior:

nuclei gets stuck and fails to start execution.

Additional Information:

  • Test code: func TestDoCmdNode1(t *testing.T) { ... }
  • nuclei version: v3.0.4
  • Operating system: Darwin VUnderline51pwn.local 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:54:10 PST 2023; root:xnu-10002.61.3~2/RELEASE_X86_64 x86_64

test code

var re1 = regexp.MustCompile(` +`)

func TestNuclei(t *testing.T) {
	a := re1.Split(`nuclei -nc -silent -j -s info`, -1)
	Cmd := exec.Command(a[0], a[1:]...)
	var err error
	var wt io.WriteCloser
	var wg sync.WaitGroup
	wg.Add(2)
	if wt, err = Cmd.StdinPipe(); nil == err {
		go func() {
			defer wg.Done()
			wt.Write([]byte("https://www.paypal.com\n"))
			/*
				I am not in a hurry to close wt here, there will be more uses in the future
				At this point I hope nuclei has started running and output the results
				But we found that if wt is not closed here, http will hang and will never start execution.
				In other words, it will not friendly process and execute the stream from time to time.
				When the stream becomes larger one by one, it will cause memory overflow, the same problem., tlsx does not have this problem. It can process the stream line by line in a friendly manner without waiting for the stream to be closed.
			*/
			//wt.Close()
		}()
	} else {
		fmt.Println(err)
	}
	if out, err1 := Cmd.StdoutPipe(); nil == err1 {
		go func() {
			defer wg.Done()
			buf := make([]byte, 4096) // 设置适当的缓冲区大小
			for {
				n, err8 := out.Read(buf)
				if 0 < n {
					os.Stdout.Write(buf[:n])
				}
				if err8 == io.EOF {
					break
				}
				if err8 != nil {
					log.Println(err8)
					break
				}
			}
		}()
	} else {
		log.Println(err)
	}
	if err4 := Cmd.Start(); nil != err4 {
		log.Println("Cmd.Start", err4)
	}

	if err6 := Cmd.Wait(); nil != err6 {
		log.Println("Cmd.Wait", err6)
	}
	wg.Wait()
	wt.Close()
}

hktalent avatar Jan 01 '24 10:01 hktalent