Skip to content

fix(interactsh): serialize InternalEvent access - #7322

Merged
Mzack9999 merged 1 commit into
devfrom
dwisiswant0/fix/interactsh/serialize-InternalEvent-access
May 7, 2026
Merged

Mzack9999 merged 1 commit into
devfrom
dwisiswant0/fix/interactsh/serialize-InternalEvent-access

Conversation

@dwisiswant0

@dwisiswant0 dwisiswant0 commented Apr 2, 2026 •

Copy link
Copy Markdown
Member

Proposed changes

fix(interactsh): serialize InternalEvent access

interactsh.(*Client).processInteractionForRequest
was updating the wrapped event under lock but
releasing it before calling Operators.Execute(),
allowing async interactsh updates to race with
matcher expr evaluation on the same InternalEvent
map, causing fatal concurrent map iteration/write
crashes.

Hold the event lock while populating interactsh
fields and running operators, and use a locked
eventHash() helper for matched-template cache
lookups that access the same event data.

Fixes #7319

Proof

patch:

$ go test -count=1 -v -run ^TestProcessInteractionForRequestConcurrentEventUpdate$ ./pkg/protocols/common/interactsh
=== RUN   TestProcessInteractionForRequestConcurrentEventUpdate
--- PASS: TestProcessInteractionForRequestConcurrentEventUpdate (0.50s)
PASS
ok  	github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh	0.597s

dev:

$ go test -count=1 -v -run ^TestProcessInteractionForRequestConcurrentEventUpdate$ ./pkg/protocols/common/interactsh
=== RUN   TestProcessInteractionForRequestConcurrentEventUpdate
fatal error: concurrent map iteration and map write

goroutine 34 [running]:
internal/runtime/maps.fatal({0x1bc97f5?, 0x17d79a0?})
	/usr/local/go/src/runtime/panic.go:1181 +0x18
internal/runtime/maps.(*Iter).Next(0x17d79a0?)
	/usr/local/go/src/internal/runtime/maps/table.go:819 +0x86
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions.getFunctionsNames(...)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/expressions/expressions.go:186
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions.isExpression({0x2b55c9eca002, 0x4}, 0x2b55c9c9b2f0)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/expressions/expressions.go:142 +0x1aa
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions.FindExpressions({0x2b55c9eca000?, 0x0?}, {0x1b151ba, 0x2}, {0x1b151bc, 0x2}, 0x2b55c9c9b2f0)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/expressions/expressions.go:120 +0x245
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions.evaluate({0x2b55c9eca000, 0x992}, 0x2b55c9c9b2f0)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/expressions/expressions.go:46 +0x53
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions.Evaluate(...)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/expressions/expressions.go:31
github.com/projectdiscovery/nuclei/v3/pkg/operators/matchers.(*Matcher).MatchWords(0x2b55cad9c000, {0x1b89388?, 0x428145?}, 0x60?)
	/home/dw1/Development/PD/nuclei/pkg/operators/matchers/match.go:68 +0x129
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh.TestProcessInteractionForRequestConcurrentEventUpdate.func1(0x2b55c9c9b2f0, 0x2b55cad9c000)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/interactsh/interactsh_test.go:60 +0x6d
github.com/projectdiscovery/nuclei/v3/pkg/operators.(*Operators).Execute(0x2b55c9c200c0, 0x2b55c9c9b2f0, 0x2b55c97d40f0, 0x24ef390, 0x0)
	/home/dw1/Development/PD/nuclei/pkg/operators/operators.go:303 +0xb08
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh.(*Client).processInteractionForRequest(0x2b55cada3e98, 0x2b55c992c4d0, 0x2b55c9d76700)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/interactsh/interactsh.go:169 +0x358
github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh.TestProcessInteractionForRequestConcurrentEventUpdate(0x2b55c98bcd88)
	/home/dw1/Development/PD/nuclei/pkg/protocols/common/interactsh/interactsh_test.go:85 +0x7f2
testing.tRunner(0x2b55c98bcd88, 0x24ef2d0)
	/usr/local/go/src/testing/testing.go:2036 +0xea
created by testing.(*T).Run in goroutine 1
	/usr/local/go/src/testing/testing.go:2101 +0x4c5
FAIL	github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh	0.100s
FAIL

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Summary by CodeRabbit

  • Bug Fixes

    • Improved concurrent event handling to prevent race conditions during template matching and event processing.
    • Enhanced error logging for operator execution to ensure proper synchronization.
  • Tests

    • Added comprehensive testing for concurrent event updates during interaction processing.

`interactsh.(*Client).processInteractionForRequest`
was updating the wrapped event under lock but
releasing it before calling `Operators.Execute()`,
allowing async interactsh updates to race with
matcher expr evaluation on the same `InternalEvent`
map, causing fatal concurrent map iteration/write
crashes.

Hold the event lock while populating interactsh
fields and running operators, and use a locked
`eventHash()` helper for matched-template cache
lookups that access the same event data.

Fixes #7319

Signed-off-by: Dwi Siswanto <git@dw1.io>
@auto-assign
auto-assign Bot requested a review from dogancanbakir April 2, 2026 04:51
@coderabbitai

coderabbitai Bot commented Apr 2, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Updated interactsh event processing to use a hash wrapper function instead of directly hashing event data, preventing concurrent map iteration issues during template matching. Refactored operator execution error handling to ensure proper unlock sequencing, and added a concurrent event mutation test to validate thread-safety.

Changes

Cohort / File(s) Summary
Event Hash & Cache Updates
pkg/protocols/common/interactsh/interactsh.go
Introduced eventHash() wrapper function for template-match cache lookups. Updated early-exit checks in polling callback and RequestEvent, cache writes via matchedTemplates.SetWithExpire, and AlreadyMatched membership checks to use the new hash wrapper. Refactored operator execution error logging to ensure data.Event.Unlock() executes before logging when operators are nil, preserving locking semantics.
Concurrent Event Update Test
pkg/protocols/common/interactsh/interactsh_test.go
Added TestProcessInteractionForRequestConcurrentEventUpdate to validate thread-safe event processing. Test constructs an event with dynamic keys, triggers concurrent mutations (lock/unlock/modify/delete cycles) during operator matching, and verifies no panics or incorrect matches occur under concurrent access patterns.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A race condition caught, a map now safe and sound,
With hashing guards and locks that keep our events homebound,
Concurrent dancers twirl—no crashes, no despair,
The Interactsh polls on, through mutex'd mountain air! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main fix: serializing InternalEvent access to prevent race conditions in the interactsh package.
Linked Issues check ✅ Passed The PR directly addresses all coding objectives from issue #7319: it prevents concurrent map iteration/write panics by holding the event lock during operator execution and cache lookups, and includes a test validating the fix.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the interactsh race condition: lock serialization in event processing, eventHash helper for thread-safe cache access, and a focused concurrency test.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dwisiswant0/fix/interactsh/serialize-InternalEvent-access

Comment @coderabbitai help to get the list of available commands and usage tips.

@neo-by-projectdiscovery-dev

neo-by-projectdiscovery-dev Bot commented Apr 2, 2026 •

Copy link
Copy Markdown

Neo - PR Security Review

No security issues found

Comment @pdneo help for available commands. · Open in Neo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pkg/protocols/common/interactsh/interactsh_test.go (1)

55-60: Consider adding a brief comment explaining the synchronization pattern.

The MatchFunc closure orchestrates the race condition scenario, but the purpose isn't immediately obvious.

📝 Suggested documentation improvement
 		MatchFunc: func(data map[string]interface{}, matcher *matchers.Matcher) (bool, []string) {
+			// Signal writer goroutine to start mutating while we're in the middle of matching.
+			// With the fix, the writer will block waiting for the lock that processInteractionForRequest holds.
 			startWriter.Do(func() {
 				close(writerStarted)
 			})
+			// Yield to allow writer goroutine to be scheduled (it will block on the lock).
 			runtime.Gosched()
 			return matcher.MatchWords("not-present-in-corpus", data)
 		},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/protocols/common/interactsh/interactsh_test.go` around lines 55 - 60, Add
a short comment inside the MatchFunc closure (near startWriter.Do,
close(writerStarted), and runtime.Gosched()) that explains the synchronization
pattern: that startWriter.Do signals the writer goroutine to begin by closing
writerStarted, runtime.Gosched is used to yield the scheduler to increase the
likelihood of the race for the test, and
matcher.MatchWords("not-present-in-corpus", data) is then evaluated to exercise
the race condition; reference the symbols MatchFunc, startWriter, writerStarted,
runtime.Gosched, and matcher.MatchWords to make the intent and safety of the
ordering explicit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/protocols/common/interactsh/interactsh_test.go`:
- Around line 55-60: Add a short comment inside the MatchFunc closure (near
startWriter.Do, close(writerStarted), and runtime.Gosched()) that explains the
synchronization pattern: that startWriter.Do signals the writer goroutine to
begin by closing writerStarted, runtime.Gosched is used to yield the scheduler
to increase the likelihood of the race for the test, and
matcher.MatchWords("not-present-in-corpus", data) is then evaluated to exercise
the race condition; reference the symbols MatchFunc, startWriter, writerStarted,
runtime.Gosched, and matcher.MatchWords to make the intent and safety of the
ordering explicit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: aa46cbb1-277c-46ad-8ac1-18d8f8a3677c

📥 Commits

Reviewing files that changed from the base of the PR and between c6fb1ae and 68e49a7.

📒 Files selected for processing (2)
  • pkg/protocols/common/interactsh/interactsh.go
  • pkg/protocols/common/interactsh/interactsh_test.go

@dwisiswant0
dwisiswant0 requested a review from Mzack9999 May 4, 2026 21:57
@Mzack9999
Mzack9999 merged commit 89d0e65 into dev May 7, 2026
21 checks passed
@Mzack9999
Mzack9999 deleted the dwisiswant0/fix/interactsh/serialize-InternalEvent-access branch May 7, 2026 20:11
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
nuclei 3.9.0

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre>## What's Changed

### 🎉 New Features
* Added support for protocol redirects by @Mzack9999 in projectdiscovery/nuclei#7296
* Added impacket integration by @Mzack9999 in projectdiscovery/nuclei#7356
* Added wmi, tsch, scmr, and dcom helper modules for JS by @dwisiswant0 in projectdiscovery/nuclei#7388
* Added mirroring of -config, -report-config, and -dashboard flags for SDK callers by @ShubhamRasal in projectdiscovery/nuclei#7393


### 🐞 Bug Fixes
* Fixed DNS variables resolving issue by @Mzack9999 in projectdiscovery/nuclei#7379
* Fixed expressions to prefer exact placeholders over expressions by @dwisiswant0 in projectdiscovery/nuclei#7397
* Fixed an issue in JS where runtimes that outlive the interrupt grace period are not abandoned, by @Mzack9999 in projectdiscovery/nuclei#7378
* Fixed an issue in reporting/jira where status-not was not matched against the transition target status name by @knakul853 in projectdiscovery/nuclei#7361
* Fixed runner to write unsigned-templates warning (WRN) to stderr by @ChrisJr404 in projectdiscovery/nuclei#7371
* Fixed `InternalEvent` access serialization in interactsh by @dwisiswant0 in projectdiscovery/nuclei#7322
* Fixed workflow to ensure context is properly propagated to child and race steps by @dwisiswant0 in projectdiscovery/nuclei#7383
* Fixed reporting/gitlab by bumping client-go to v1.9.1 and widening IDs to int64 by @ShubhamRasal in projectdiscovery/nuclei#7398
* Fixed memogen to skip context correctly and auto-push scope to upstream by @Mzack9999 in projectdiscovery/nuclei#7419
* Fixed a slice-bounds panic in telnetmini's ParseNTLMResponse when handling truncated NTLM challenges by @tejgokani in projectdiscovery/nuclei#7425
* Fixed SMBv1 probing in JS to occur after SMB2 negotiation by @dwisiswant0 in projectdiscovery/nuclei#7430
* Fixed templates to reject unknown fields when loading JSON templates by @tejgokani in projectdiscovery/nuclei#7453
* Fixed persistence of QueryAuthStrategy parameters in ApplyAuthStrategy by @akhilesharora in projectdiscovery/nuclei#7410
* Fixed loader to warn when templates are excluded by `.nuclei-ignore` tags by @dogancanbakir in projectdiscovery/nuclei#7452

### Other Changes
* Splitted exact matches and pattern handling in catalog for improved performance by @mikhail5555 in projectdiscovery/nuclei#7340
* Updated README_PT-BR.md to reflect current project description and features by @gugacyber in projectdiscovery/nuclei#7405
* Fixed broken cloud scanning link by @dogancanbakir in projectdiscovery/nuclei#7413
* Bumped pdsec modules + govaluate/aurora migration by @dogancanbakir in projectdiscovery/nuclei#7414
* Dropped vulnerable docker/docker dependency by @dogancanbakir in projectdiscovery/nuclei#7447
* Used path-aware filesystem containment checks by @dwisiswant0 in projectdiscovery/nuclei#7420
* Centralized runtime session handling by @dwisiswant0 in projectdiscovery/nuclei#7449


## New Contributors
* @ChrisJr404 made their first contribution in projectdiscovery/nuclei#7371
* @gugacyber made their first contribution in projectdiscovery/nuclei#7405
* @akhilesharora made their first contribution in projectdiscovery/nuclei#7410
* @tejgokani made their first contribution in projectdiscovery/nuclei#7425

**Full Changelog**: https://github.com/projectdiscovery/nuclei/compare/v3.8.0...v3.9.0</pre>
  <p>View the full release notes at <a href="https://github.com/projectdiscovery/nuclei/releases/tag/v3.9.0">https://github.com/projectdiscovery/nuclei/releases/tag/v3.9.0</a>.</p>
</details>
<hr>

See merge request: Harmonybrew/homebrew-core!11229
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fatal error: concurrent map iteration and map write with Interactsh in v3.7.1

2 participants