Skip to content

Commit

Permalink
scan error formatting (#5628)
Browse files Browse the repository at this point in the history
  • Loading branch information
tarunKoyalwar authored Sep 13, 2024
1 parent 2ac9aaf commit 87e99be
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 41 deletions.
27 changes: 10 additions & 17 deletions pkg/scan/scan_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
"github.com/projectdiscovery/utils/errkit"
)

type ScanContextOption func(*ScanContext)
Expand All @@ -30,7 +31,7 @@ type ScanContext struct {
OnWarning func(string)

// unexported state fields
errors []error
error error
warnings []string
events []*output.InternalWrappedEvent
results []*output.ResultEvent
Expand All @@ -52,8 +53,8 @@ func (s *ScanContext) Context() context.Context {
return s.ctx
}

func (s *ScanContext) GenerateErrorMessage() string {
return joinErrors(s.errors)
func (s *ScanContext) GenerateErrorMessage() error {
return s.error
}

// GenerateResult returns final results slice from all events
Expand Down Expand Up @@ -94,13 +95,16 @@ func (s *ScanContext) LogError(err error) {
if err == nil {
return
}

if s.OnError != nil {
s.OnError(err)
}
s.errors = append(s.errors, err)
if s.error == nil {
s.error = err
} else {
s.error = errkit.Append(s.error, err)
}

errorMessage := s.GenerateErrorMessage()
errorMessage := s.GenerateErrorMessage().Error()

for _, result := range s.results {
result.Error = errorMessage
Expand Down Expand Up @@ -129,14 +133,3 @@ func (s *ScanContext) LogWarning(format string, args ...any) {
}
}
}

// joinErrors joins multiple errors and returns a single error string
func joinErrors(errors []error) string {
var errorMessages []string
for _, e := range errors {
if e != nil {
errorMessages = append(errorMessages, e.Error())
}
}
return strings.Join(errorMessages, "; ")
}
43 changes: 19 additions & 24 deletions pkg/tmplexec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/flow"
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/generic"
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/multiproto"
"github.com/projectdiscovery/nuclei/v3/pkg/types/nucleierr"
"github.com/projectdiscovery/utils/errkit"
)

Expand Down Expand Up @@ -207,7 +206,7 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
ctx.LogError(errx)

if lastMatcherEvent != nil {
lastMatcherEvent.InternalEvent["error"] = tryParseCause(fmt.Errorf("%s", ctx.GenerateErrorMessage()))
lastMatcherEvent.InternalEvent["error"] = getErrorCause(ctx.GenerateErrorMessage())
writeFailureCallback(lastMatcherEvent, e.options.Options.MatcherStatus)
}

Expand All @@ -222,7 +221,7 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
Info: e.options.TemplateInfo,
Type: e.getTemplateType(),
Host: ctx.Input.MetaInput.Input,
Error: tryParseCause(fmt.Errorf("%s", ctx.GenerateErrorMessage())),
Error: getErrorCause(ctx.GenerateErrorMessage()),
},
},
OperatorsResult: &operators.Result{
Expand All @@ -235,31 +234,27 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
return executed.Load() || matched.Load(), errx
}

// tryParseCause tries to parse the cause of given error
// getErrorCause tries to parse the cause of given error
// this is legacy support due to use of errorutil in existing libraries
// but this should not be required once all libraries are updated
func tryParseCause(err error) string {
errStr := ""
errX := errkit.FromError(err)
if errX != nil {
var errCause error

if len(errX.Errors()) > 1 {
errCause = errX.Errors()[0]
}
if errCause == nil {
errCause = errX
func getErrorCause(err error) string {
if err == nil {
return ""
}
errx := errkit.FromError(err)
var cause error
for _, e := range errx.Errors() {
if e != nil && strings.Contains(e.Error(), "context deadline exceeded") {
continue
}

msg := strings.Trim(errCause.Error(), "{} ")
parts := strings.Split(msg, ":")
errCause = errkit.New("%s", parts[len(parts)-1])
errKind := errkit.GetErrorKind(err, nucleierr.ErrTemplateLogic).String()
errStr = errCause.Error()
errStr = strings.TrimSpace(strings.Replace(errStr, "errKind="+errKind, "", -1))
cause = e
break
}

return errStr
if cause == nil {
cause = errkit.Append(errkit.New("could not get error cause"), errx)
}
// parseScanError prettifies the error message and removes everything except the cause
return parseScanError(cause.Error())
}

// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
Expand Down
39 changes: 39 additions & 0 deletions pkg/tmplexec/interface.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package tmplexec

import (
"errors"
"regexp"
"strings"

"github.com/projectdiscovery/nuclei/v3/pkg/scan"
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/flow"
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/generic"
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/multiproto"
"github.com/projectdiscovery/utils/errkit"
)

var (
Expand All @@ -30,3 +35,37 @@ type TemplateEngine interface {
// Name returns name of template engine
Name() string
}

var (
// A temporary fix to remove errKind from error message
// this is because errkit is not used everywhere yet
reNoKind = regexp.MustCompile(`([\[][^][]+[\]]|errKind=[^ ]+) `)
)

// parseScanError parses given scan error and only returning the cause
// instead of inefficient one
func parseScanError(msg string) string {
if msg == "" {
return ""
}
if strings.HasPrefix(msg, "ReadStatusLine:") {
// last index is actual error (from rawhttp)
parts := strings.Split(msg, ":")
msg = strings.TrimSpace(parts[len(parts)-1])
}
if strings.Contains(msg, "read ") {
// same here
parts := strings.Split(msg, ":")
msg = strings.TrimSpace(parts[len(parts)-1])
}
e := errkit.FromError(errors.New(msg))
for _, err := range e.Errors() {
if err != nil && strings.Contains(err.Error(), "context deadline exceeded") {
continue
}
msg = reNoKind.ReplaceAllString(err.Error(), "")
return msg
}
wrapped := errkit.Append(errkit.New("failed to get error cause"), e).Error()
return reNoKind.ReplaceAllString(wrapped, "")
}

0 comments on commit 87e99be

Please sign in to comment.