Skip to content

fatal error: concurrent map writes in evaluateVarsWithInteractsh during fuzzing #6827

@yusei-wy

Description

@yusei-wy

Description

When running fuzzing templates with interactsh enabled and concurrency > 1, evaluateVarsWithInteractsh in pkg/fuzz/execute.go causes fatal error: concurrent map writes.

Root Cause

The data map parameter is modified in-place (lines 235, 251) inside the if rule.options.Interactsh != nil block:

for k, v := range data {           // READ
    data[k] = got                  // WRITE (L235)
    expressions.Evaluate(got, data) // data is READ here via replacer.Replace
    data[k] = evaluatedData        // WRITE (L251)
}

When multiple goroutines execute fuzzing rules concurrently, they can write to the same map simultaneously, causing a data race.

Stack Trace

fatal error: concurrent map writes

goroutine N [running]:
github.com/projectdiscovery/nuclei/v3/pkg/fuzz.(*Rule).evaluateVarsWithInteractsh(...)
    pkg/fuzz/execute.go:247
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions.evaluate(...)
    pkg/protocols/common/expressions/expressions.go:47
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer.Replace(...)
    pkg/protocols/common/replacer/replacer.go:15

Reproduction

The race condition can be reproduced with the following test (run with go test -race):

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()
}

Proposed Fix

Clone the data map before modification in evaluateVarsWithInteractsh:

if rule.options.Interactsh != nil {
    data = maps.Clone(data)
    // ... rest of the function
}

Environment

  • nuclei version: v3.6.2 (also affects dev branch)
  • OS: darwin/linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugInconsistencies or issues which will cause an issue or problem for users or implementors.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions