scan error formatting (#5628)

This commit is contained in:
Tarun Koyalwar 2024-09-14 00:06:08 +05:30 committed by GitHub
parent 2ac9aaf871
commit 87e99be4f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 42 deletions

View File

@ -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)
@ -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
@ -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
@ -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
@ -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, "; ")
}

View File

@ -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"
)
@ -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)
}
@ -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{
@ -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]
func getErrorCause(err error) string {
if err == nil {
return ""
}
if errCause == nil {
errCause = errX
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.

View File

@ -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 (
@ -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, "")
}