Skip to content

fix(gogo): populate pkg.ChainExec when injecting neutron templates#31

Merged
wuchulonly merged 2 commits into
chainreactors:masterfrom
wuchulonly:fix/gogo-chainexec-nil-panic
Jul 7, 2026
Merged

fix(gogo): populate pkg.ChainExec when injecting neutron templates#31
wuchulonly merged 2 commits into
chainreactors:masterfrom
wuchulonly:fix/gogo-chainexec-nil-panic

Conversation

@wuchulonly

@wuchulonly wuchulonly commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Symptom

Any gogo scan with exploit enabled (RunnerOption.Exploit != "none") panics per open host:

[ants]: worker exits from panic: runtime error: invalid memory address or nil pointer dereference
neutron/templates.(*ChainExecutor).Execute(0x0, ...)            templates/chain.go:80
gogo/v2/engine.executeTemplates ...                            engine/neutronScan.go:37
gogo/v2/engine.NeutronScan / engine.Dispatch ...
sdk/gogo.(*Engine).workflowStream.func2.2 ...                  gogo/gogo.go

The receiver is 0x0: engine.NeutronScan drives the package-global pkg.ChainExec, which is only ever assigned by pkg.LoadTemplates.

Root cause

applyInjectedNeutron injects templates by setting pkg.TemplateMap directly and never goes through pkg.LoadTemplates, so pkg.ChainExec is left nil. executeTemplates finds a populated TemplateMap (non-empty startIDs) and then calls ChainExec.Execute(...) on the nil global → panic at chain.go:80 (e.config.DepthFirst). The ants pool swallows it, so the process survives but the host's result is silently dropped and the log is spammed.

Fix

Build the ChainExecutor alongside TemplateMap in applyInjectedNeutron, doing the same id → chains registration pkg.LoadTemplates already performs. This keeps the two gogo package globals consistent on the injected-template path. No signature or dependency changes (neutron/templates is already a transitive dep; types.Template is an alias of templates.Template).

Test

gogo/gogo_chainexec_test.go covers the new helper: id/chain registration, entrypoint resolution, and a chain walk (the exact call that hit the nil receiver).

Verified downstream in aiscan — constructing the gogo engine with an injected neutron engine now leaves pkg.ChainExec != nil; reverting this patch makes that assertion fail.

🤖 Generated with Claude Code

Nathaniel Leonardjoi and others added 2 commits July 7, 2026 04:38
engine.NeutronScan drives the package-global pkg.ChainExec, which is only
ever assigned by pkg.LoadTemplates. applyInjectedNeutron injects templates
by setting pkg.TemplateMap directly and bypasses LoadTemplates, so
pkg.ChainExec stays nil. Any exploit scan (RunnerOption.Exploit != "none")
then calls ChainExec.Execute on a nil receiver, panicking inside
engine.NeutronScan -> executeTemplates. The panic is caught only by the
ants scan pool ("worker exits from panic"), which silently drops that
host's result.

Build the ChainExecutor alongside TemplateMap (same registration gogo's
own pkg.LoadTemplates performs) so the injected-template path keeps the
two package globals consistent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both fail on master independently of the ChainExec fix; bundled here so
this PR's CI can go green (requested by maintainer).

- neutron/config_templates_test.go: OperatorResult (= parsers.NeutronResult)
  now embeds parsers.Result, so Matched is a promoted field that cannot be
  set in a composite literal. Assign it after construction.
  (Was: "unknown field Matched in struct literal" -> neutron [build failed].)

- proton/engine_test.go TestEngine_ConfigFilter_IDs: the file extractor
  filters out dummy values like "test", so `password = test` yielded 0
  findings. Use a realistic value ("test123", as the sibling Execute test
  already does); keep "PRIVATE KEY" in the input to assert the excluded
  private-key-detect rule does not fire.

Not touched: examples/cases/spray_crawl_finger.TestSprayCrawlAndDeepFinger
fast-failed (~0.9s, not a timeout) once in CI but passes 15/15 locally and
shows no data race; it is flaky under parallel-package load, not stale.
Left as-is rather than hack an assertion I cannot reproduce failing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wuchulonly wuchulonly merged commit 686d4bf into chainreactors:master Jul 7, 2026
2 checks passed
wuchulonly pushed a commit to chainreactors/aiscan that referenced this pull request Jul 7, 2026
Drop the local replace bridge and pin github.com/chainreactors/sdk to
v0.3.4-0.20260707120839-686d4bfa2b2b (chainreactors/sdk#31, merged), which
populates gogo's pkg.ChainExec when the SDK injects neutron templates. This
fixes the ants "worker exits from panic" nil-pointer that aborted exploit
scanning on every open host.

TestGogoEngineInjectsChainExecutor now passes against the real pinned SDK
(no replace).

Refs #51

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant