Repository navigation
fix(js): abandon runtimes that outlive interrupt grace period - #7378
Conversation
WalkthroughAbandons goja runtimes that fail to terminate after an interrupt, delegates orphan cleanup to a reaper, ensures pool slots aren't released until orphans exit, and adds tests verifying abandonment, slot release ordering, and cleanup after callback panic. ChangesRuntime Pool Race Condition Fix
sequenceDiagram
participant Caller
participant executeWithPoolingProgram
participant executeWithRuntime
participant Context as ctx.Done
participant GojaRuntime as goja.Runtime
participant Pool as sync.Pool
participant Reaper
Caller->>executeWithPoolingProgram: ExecuteProgram(program, opts)
executeWithPoolingProgram->>Pool: Get runtime
executeWithPoolingProgram->>executeWithRuntime: run program with ctx
executeWithRuntime->>Context: ctx.Done() (deadline)
executeWithRuntime->>GojaRuntime: Interrupt()
executeWithRuntime->>GojaRuntime: wait for run result (up to 1s)
alt run returns within grace
executeWithRuntime-->>executeWithPoolingProgram: normal result
executeWithPoolingProgram->>Pool: Put runtime back
else run does not return within 1s
executeWithRuntime-->>executeWithPoolingProgram: errRuntimeTerminationTimeout
executeWithPoolingProgram->>executeWithPoolingProgram: mark runtimeAbandoned
executeWithPoolingProgram->>Reaper: spawn onOrphanExit to wait for orphan and release slot
end
executeWithPoolingProgram-->>Caller: final result or error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Neo - PR Security ReviewNo security issues found Hardening Notes
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/js/compiler/pool.go`:
- Around line 204-208: The defer currently calls pooljsc.Done() even when
runtimeAbandoned is true, freeing the concurrency slot while the RunProgram
goroutine is still alive (see runtimeAbandoned, errRuntimeTerminationTimeout,
RunProgram, pooljsc.Done(), gojapool.Put); change the logic so that when
runtimeAbandoned==true you do NOT call pooljsc.Done() in this defer but instead
hand the abandoned runtime to a reaper: spawn a goroutine (or enqueue to a
reaper worker) that waits for the orphaned RunProgram to fully exit (or for the
runtime to be Put back via gojapool.Put) and only then calls pooljsc.Done();
apply the same conditional fix to the other defer block referenced (around the
261-264 region).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7f4d1dd9-31fc-4e50-8649-32a1c777f8fe
📒 Files selected for processing (2)
pkg/js/compiler/compiler_test.gopkg/js/compiler/pool.go
| if err := opts.Callback(runtime); err != nil { | ||
| // Inner goroutine has not been spawned yet — safe to clean up | ||
| // synchronously and return the runtime to the pool. | ||
| cleanupRuntime(runtime, args, opts) |
There was a problem hiding this comment.
I'm leaning towards deferring this cleanup to preserve UB (like panic) while cleaning runtime state before gojapool reuse. Wdyt?
There was a problem hiding this comment.
$ go test -v -run "TestExecuteWithRuntimeCleansUpAfterCallbackPanic" ./pkg/js/compiler/
=== RUN TestExecuteWithRuntimeCleansUpAfterCallbackPanic
compiler_test.go:140:
Error Trace: /home/dw1/Development/PD/nuclei/pkg/js/compiler/compiler_test.go:140
Error: Should be true
Test: TestExecuteWithRuntimeCleansUpAfterCallbackPanic
--- FAIL: TestExecuteWithRuntimeCleansUpAfterCallbackPanic (0.00s)
FAIL
FAIL github.com/projectdiscovery/nuclei/v3/pkg/js/compiler 0.107s
FAILPatch: TestExecuteWithRuntimeCleansUpAfterCallbackPanic.patch
When a runtime is abandoned, we must not touch the goja runtime after `RunProgram` has exceeded the interrupt grace period. At the same time, cleanup still needs to run on every normal exit before returning the runtime to the pool, including setup callback panics. Signed-off-by: Dwi Siswanto <git@dw1.io>
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
Proposed changes
Prevent pooled and non-pooled goja runtimes from being reused or cleaned up when
the RunProgram goroutine fails to exit after context cancellation and Interrupt().
In that state, the goroutine may still be mutating runtime state, so touching the
runtime or returning it to the pool can cause fatal concurrent map access panics.
Add an explicit errRuntimeTerminationTimeout path that abandons the runtime,
keeps the related concurrency slot reserved, and releases that slot only from a
reaper after the orphaned goroutine exits. Preserve errors.Is compatibility with
the original context cancellation cause.
Keep normal cleanup behavior unchanged, including callback panic cleanup, and add
regression tests for stuck-interrupt handling that verify runtime abandonment and
delayed slot release.
Fixes #7376
Checklist
Summary by CodeRabbit