diff --git a/cmd/integration-test/profile-loader.go b/cmd/integration-test/profile-loader.go index 177bd9955..dafc15aa2 100644 --- a/cmd/integration-test/profile-loader.go +++ b/cmd/integration-test/profile-loader.go @@ -20,8 +20,8 @@ func (h *profileLoaderByRelFile) Execute(testName string) error { if err != nil { return errorutil.NewWithErr(err).Msgf("failed to load template with id") } - if len(results) < 100 { - return fmt.Errorf("incorrect result: expected more results than %d, got %v", 100, len(results)) + if len(results) <= 10 { + return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results)) } return nil } @@ -33,12 +33,13 @@ func (h *profileLoaderById) Execute(testName string) error { if err != nil { return errorutil.NewWithErr(err).Msgf("failed to load template with id") } - if len(results) < 100 { - return fmt.Errorf("incorrect result: expected more results than %d, got %v", 100, len(results)) + if len(results) <= 10 { + return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results)) } return nil } +// this profile with load kevs type customProfileLoader struct{} func (h *customProfileLoader) Execute(filepath string) error { @@ -46,8 +47,8 @@ func (h *customProfileLoader) Execute(filepath string) error { if err != nil { return errorutil.NewWithErr(err).Msgf("failed to load template with id") } - if len(results) < 267 { - return fmt.Errorf("incorrect result: expected more results than %d, got %v", 267, len(results)) + if len(results) < 1 { + return fmt.Errorf("incorrect result: expected more results than %d, got %v", 1, len(results)) } return nil } diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index 13a7ec2c1..a74a62a64 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -414,6 +414,7 @@ on extensive configurability, massive extensibility and ease of use.`) flagSet.DynamicVar(&pdcpauth, "auth", "true", "configure projectdiscovery cloud (pdcp) api key"), flagSet.BoolVarP(&options.EnableCloudUpload, "cloud-upload", "cup", false, "upload scan results to pdcp dashboard"), flagSet.StringVarP(&options.ScanID, "scan-id", "sid", "", "upload scan results to given scan id"), + flagSet.StringVarP(&options.ScanName, "scan-name", "sname", "", "scan name to set (optional)"), ) flagSet.CreateGroup("Authentication", "Authentication", diff --git a/internal/pdcp/writer.go b/internal/pdcp/writer.go index bd0a7d471..a76d4ea31 100644 --- a/internal/pdcp/writer.go +++ b/internal/pdcp/writer.go @@ -9,6 +9,7 @@ import ( "io" "net/http" "net/url" + "regexp" "sync/atomic" "time" @@ -27,9 +28,13 @@ const ( appendEndpoint = "/v1/scans/%s/import" flushTimer = time.Duration(1) * time.Minute MaxChunkSize = 1024 * 1024 * 4 // 4 MB + xidRe = `^[a-z0-9]{20}$` ) -var _ output.Writer = &UploadWriter{} +var ( + xidRegex = regexp.MustCompile(xidRe) + _ output.Writer = &UploadWriter{} +) // UploadWriter is a writer that uploads its output to pdcp // server to enable web dashboard and more @@ -41,6 +46,7 @@ type UploadWriter struct { cancel context.CancelFunc done chan struct{} scanID string + scanName string counter atomic.Int32 } @@ -86,8 +92,17 @@ func NewUploadWriter(ctx context.Context, creds *pdcpauth.PDCPCredentials) (*Upl } // SetScanID sets the scan id for the upload writer -func (u *UploadWriter) SetScanID(id string) { +func (u *UploadWriter) SetScanID(id string) error { + if !xidRegex.MatchString(id) { + return fmt.Errorf("invalid scan id provided") + } u.scanID = id + return nil +} + +// SetScanName sets the scan name for the upload writer +func (u *UploadWriter) SetScanName(name string) { + u.scanName = name } func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { @@ -220,7 +235,13 @@ func (u *UploadWriter) getRequest(bin []byte) (*retryablehttp.Request, error) { return nil, errorutil.NewWithErr(err).Msgf("could not create cloud upload request") } // add pdtm meta params - req.URL.RawQuery = updateutils.GetpdtmParams(config.Version) + req.URL.Params.Merge(updateutils.GetpdtmParams(config.Version)) + // if it is upload endpoint also include name if it exists + if u.scanName != "" && req.URL.Path == uploadEndpoint { + req.URL.Params.Add("name", u.scanName) + } + req.URL.Update() + req.Header.Set(pdcpauth.ApiKeyHeaderName, u.creds.APIKey) req.Header.Set("Content-Type", "application/octet-stream") req.Header.Set("Accept", "application/json") diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 5319f566d..a0c46f6d0 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -414,7 +414,11 @@ func (r *Runner) setupPDCPUpload(writer output.Writer) output.Writer { return writer } if r.options.ScanID != "" { - uploadWriter.SetScanID(r.options.ScanID) + // ignore and use empty scan id if invalid + _ = uploadWriter.SetScanID(r.options.ScanID) + } + if r.options.ScanName != "" { + uploadWriter.SetScanName(r.options.ScanName) } return output.NewMultiWriter(writer, uploadWriter) } diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index b821fcc67..39d6a6ea0 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -16,6 +16,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/js/compiler" + "github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity" "github.com/projectdiscovery/nuclei/v3/pkg/operators" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators" @@ -341,6 +342,18 @@ func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, e return nil, errors.New("no template author field provided") } + // use default unknown severity + if len(template.Workflows) == 0 { + if template.Info.SeverityHolder.Severity == severity.Undefined { + // set unknown severity with counter and forced warning + template.Info.SeverityHolder.Severity = severity.Unknown + if options.Options.Validate { + // when validating return error + return nil, errors.New("no template severity field provided") + } + } + } + // Setting up variables regarding template metadata options.TemplateID = template.ID options.TemplateInfo = template.Info diff --git a/pkg/types/types.go b/pkg/types/types.go index 7a2d9b90c..0c31769ee 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -377,6 +377,8 @@ type Options struct { EnableCloudUpload bool // ScanID is the scan ID to use for cloud upload ScanID string + // ScanName is the name of the scan to be uploaded + ScanName string // JsConcurrency is the number of concurrent js routines to run JsConcurrency int // SecretsFile is file containing secrets for nuclei