diff --git a/pkg/fuzz/execute.go b/pkg/fuzz/execute.go index ddec765052..f7881333f6 100644 --- a/pkg/fuzz/execute.go +++ b/pkg/fuzz/execute.go @@ -3,6 +3,7 @@ package fuzz import ( "fmt" "io" + "maps" "regexp" "strings" @@ -222,6 +223,8 @@ func (rule *Rule) evaluateVars(input string) (string, error) { func (rule *Rule) evaluateVarsWithInteractsh(data map[string]interface{}, interactshUrls []string) (map[string]interface{}, []string) { // Check if Interactsh options are configured if rule.options.Interactsh != nil { + data = maps.Clone(data) + interactshUrlsMap := make(map[string]struct{}) for _, url := range interactshUrls { interactshUrlsMap[url] = struct{}{} diff --git a/pkg/fuzz/execute_race_test.go b/pkg/fuzz/execute_race_test.go new file mode 100644 index 0000000000..61f0e16913 --- /dev/null +++ b/pkg/fuzz/execute_race_test.go @@ -0,0 +1,32 @@ +package fuzz + +import ( + "sync" + "testing" + + "github.com/projectdiscovery/nuclei/v3/pkg/protocols" + "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh" +) + +func TestEvaluateVarsWithInteractsh_RaceCondition(t *testing.T) { + rule := &Rule{} + rule.options = &protocols.ExecutorOptions{ + Interactsh: &interactsh.Client{}, + } + + sharedData := map[string]interface{}{ + "var1": "value1", + "var2": "{{var1}}_suffix", + "var3": "prefix_{{var1}}", + } + + var wg sync.WaitGroup + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + rule.evaluateVarsWithInteractsh(sharedData, nil) + }() + } + wg.Wait() +}