mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 04:55:28 +00:00
pdcp result upload: bug fix + (optional) scan name support using -sname flag (#5155)
* add default template severity and error when validating * ignore workflows when validating severity * add scan name support in pdcp result upload * scan upload: fix missing name query param * make profile-loader integration tests generic * add scan-id validation * ignore invalid scan id's
This commit is contained in:
parent
0f983d8204
commit
d6424ea5d0
@ -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
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user