From 39b58805fc513065c11b21f6783b8580ddb2c3cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Wed, 3 Dec 2025 11:43:49 +0700 Subject: [PATCH] add strict probe for httpx --- cmd/nuclei/main.go | 1 + internal/runner/inputs.go | 18 ++++++++++-------- internal/runner/runner.go | 6 +++++- pkg/types/types.go | 2 ++ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index 1a51c9f01..721c89aeb 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -434,6 +434,7 @@ on extensive configurability, massive extensibility and ease of use.`) }), flagSet.DurationVarP(&options.InputReadTimeout, "input-read-timeout", "irt", time.Duration(3*time.Minute), "timeout on input read"), flagSet.BoolVarP(&options.DisableHTTPProbe, "no-httpx", "nh", false, "disable httpx probing for non-url input"), + flagSet.BoolVarP(&options.StrictProbe, "strict-probe", "sp", false, "stop scanning when httpx probe returns 0 URLs (no fallback to raw input)"), flagSet.BoolVar(&options.DisableStdin, "no-stdin", false, "disable stdin processing"), ) diff --git a/internal/runner/inputs.go b/internal/runner/inputs.go index cb782f736..083e5bdc8 100644 --- a/internal/runner/inputs.go +++ b/internal/runner/inputs.go @@ -19,14 +19,15 @@ import ( // initializeTemplatesHTTPInput initializes the http form of input // for any loaded http templates if input is in non-standard format. -func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) { +// Returns the hybrid map, the count of URLs found, and an error. +func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, int32, error) { hm, err := hybrid.New(hybrid.DefaultDiskOptions) if err != nil { - return nil, errors.Wrap(err, "could not create temporary input file") + return nil, 0, errors.Wrap(err, "could not create temporary input file") } if r.inputProvider.InputType() == provider.MultiFormatInputProvider { // currently http probing for input mode types is not supported - return hm, nil + return hm, 0, nil } r.Logger.Info().Msgf("Running httpx on input host") @@ -41,19 +42,19 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) { dialers := protocolstate.GetDialersWithId(r.options.ExecutionId) if dialers == nil { - return nil, fmt.Errorf("dialers not initialized for %s", r.options.ExecutionId) + return nil, 0, fmt.Errorf("dialers not initialized for %s", r.options.ExecutionId) } httpxOptions.NetworkPolicy = dialers.NetworkPolicy httpxClient, err := httpx.New(&httpxOptions) if err != nil { - return nil, errors.Wrap(err, "could not create httpx client") + return nil, 0, errors.Wrap(err, "could not create httpx client") } // Probe the non-standard URLs and store them in cache swg, err := syncutil.New(syncutil.WithSize(r.options.BulkSize)) if err != nil { - return nil, errors.Wrap(err, "could not create adaptive group") + return nil, 0, errors.Wrap(err, "could not create adaptive group") } var count atomic.Int32 r.inputProvider.Iterate(func(value *contextargs.MetaInput) bool { @@ -80,6 +81,7 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) { }) swg.Wait() - r.Logger.Info().Msgf("Found %d URL from httpx", count.Load()) - return hm, nil + urlCount := count.Load() + r.Logger.Info().Msgf("Found %d URL from httpx", urlCount) + return hm, urlCount, nil } diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 0c5573519..260b1c783 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -701,10 +701,14 @@ func (r *Runner) RunEnumeration() error { // are used, and if inputs are non-http to pre-perform probing // of urls and storing them for execution. if !r.options.DisableHTTPProbe && loader.IsHTTPBasedProtocolUsed(store) && r.isInputNonHTTP() { - inputHelpers, err := r.initializeTemplatesHTTPInput() + inputHelpers, urlCount, err := r.initializeTemplatesHTTPInput() if err != nil { return errors.Wrap(err, "could not probe http input") } + if r.options.StrictProbe && urlCount == 0 { + r.Logger.Info().Msgf("Strict probe mode: No URLs found from httpx probe, skipping scan") + return nil + } executorOpts.InputHelper.InputsHTTP = inputHelpers } diff --git a/pkg/types/types.go b/pkg/types/types.go index daed01908..a0c36c2ca 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -201,6 +201,8 @@ type Options struct { DebugResponse bool // DisableHTTPProbe disables http probing feature of input normalization DisableHTTPProbe bool + // StrictProbe stops scanning when httpx probe returns 0 URLs (no fallback to raw input) + StrictProbe bool // LeaveDefaultPorts skips normalization of default ports LeaveDefaultPorts bool // AutomaticScan enables automatic tech based template execution