mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 21:25:27 +00:00
RES-84 # Improve Nuclei CLI interface (WIP)
* removed the generic isEmpty implementation
This commit is contained in:
parent
68a6d394e7
commit
2f162e859e
@ -123,7 +123,7 @@ func New(options *types.Options) (*Runner, error) {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utils.IsEmpty(options.Templates) || !options.NewTemplates || (utils.IsEmpty(options.Targets, options.Target) && utils.IsNotEmpty(options.Stdin))) && options.UpdateTemplates {
|
if (len(options.Templates) == 0 || !options.NewTemplates || (options.Targets == "" && !options.Stdin && options.Target == "")) && options.UpdateTemplates {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
hm, err := hybrid.New(hybrid.DefaultDiskOptions)
|
hm, err := hybrid.New(hybrid.DefaultDiskOptions)
|
||||||
@ -211,7 +211,7 @@ func New(options *types.Options) (*Runner, error) {
|
|||||||
// create project file if requested or load existing one
|
// create project file if requested or load existing one
|
||||||
if options.Project {
|
if options.Project {
|
||||||
var projectFileErr error
|
var projectFileErr error
|
||||||
runner.projectFile, projectFileErr = projectfile.New(&projectfile.Options{Path: options.ProjectPath, Cleanup: utils.IsEmpty(options.ProjectPath)})
|
runner.projectFile, projectFileErr = projectfile.New(&projectfile.Options{Path: options.ProjectPath, Cleanup: utils.IsBlank(options.ProjectPath)})
|
||||||
if projectFileErr != nil {
|
if projectFileErr != nil {
|
||||||
return nil, projectFileErr
|
return nil, projectFileErr
|
||||||
}
|
}
|
||||||
@ -354,10 +354,10 @@ func (r *Runner) RunEnumeration() error {
|
|||||||
if r.interactsh != nil {
|
if r.interactsh != nil {
|
||||||
gologger.Info().Msgf("Using Interactsh Server %s", r.options.InteractshURL)
|
gologger.Info().Msgf("Using Interactsh Server %s", r.options.InteractshURL)
|
||||||
}
|
}
|
||||||
if utils.IsNotEmpty(store.Templates()) {
|
if len(store.Templates()) > 0 {
|
||||||
gologger.Info().Msgf("Templates loaded: %d (New: %d)", len(store.Templates()), r.countNewTemplates())
|
gologger.Info().Msgf("Templates loaded: %d (New: %d)", len(store.Templates()), r.countNewTemplates())
|
||||||
}
|
}
|
||||||
if utils.IsNotEmpty(store.Workflows()) {
|
if len(store.Workflows()) > 0 {
|
||||||
gologger.Info().Msgf("Workflows loaded: %d", len(store.Workflows()))
|
gologger.Info().Msgf("Workflows loaded: %d", len(store.Workflows()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,8 +367,8 @@ func (r *Runner) RunEnumeration() error {
|
|||||||
var unclusteredRequests int64
|
var unclusteredRequests int64
|
||||||
for _, template := range store.Templates() {
|
for _, template := range store.Templates() {
|
||||||
// workflows will dynamically adjust the totals while running, as
|
// workflows will dynamically adjust the totals while running, as
|
||||||
// it can't be know in advance which requests will be called
|
// it can't be known in advance which requests will be called
|
||||||
if utils.IsNotEmpty(template.Workflows) {
|
if len(template.Workflows) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
unclusteredRequests += int64(template.TotalRequests) * r.inputCount
|
unclusteredRequests += int64(template.TotalRequests) * r.inputCount
|
||||||
@ -419,7 +419,7 @@ func (r *Runner) RunEnumeration() error {
|
|||||||
|
|
||||||
var totalRequests int64
|
var totalRequests int64
|
||||||
for _, t := range finalTemplates {
|
for _, t := range finalTemplates {
|
||||||
if utils.IsNotEmpty(t.Workflows) {
|
if len(t.Workflows) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
totalRequests += int64(t.TotalRequests) * r.inputCount
|
totalRequests += int64(t.TotalRequests) * r.inputCount
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/internal/severity"
|
"github.com/projectdiscovery/nuclei/v2/internal/severity"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TagFilter is used to filter nuclei templates for tag based execution
|
// TagFilter is used to filter nuclei templates for tag based execution
|
||||||
@ -46,7 +45,7 @@ func (tagFilter *TagFilter) Match(templateTags, templateAuthors []string, templa
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsNotEmpty(tagFilter.severities) {
|
if len(tagFilter.severities) > 0 {
|
||||||
if _, ok := tagFilter.severities[templateSeverity]; !ok {
|
if _, ok := tagFilter.severities[templateSeverity]; !ok {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@ -56,7 +55,7 @@ func (tagFilter *TagFilter) Match(templateTags, templateAuthors []string, templa
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isAuthorMatch(templateAuthors []string, tagFilter *TagFilter) bool {
|
func isAuthorMatch(templateAuthors []string, tagFilter *TagFilter) bool {
|
||||||
if utils.IsEmpty(tagFilter.authors) {
|
if len(tagFilter.authors) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +69,7 @@ func isAuthorMatch(templateAuthors []string, tagFilter *TagFilter) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isTagMatch(templateTags []string, tagFilter *TagFilter) bool {
|
func isTagMatch(templateTags []string, tagFilter *TagFilter) bool {
|
||||||
if utils.IsEmpty(tagFilter.allowedTags) {
|
if len(tagFilter.allowedTags) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +100,7 @@ func (tagFilter *TagFilter) MatchWithWorkflowTags(templateTags, templateAuthors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsNotEmpty(workflowAllowedTagMap) { // TODO review, does not seem to make sense
|
if len(workflowAllowedTagMap) > 0 { // TODO review, does not seem to make sense
|
||||||
for _, templateTag := range templateTags {
|
for _, templateTag := range templateTags {
|
||||||
if _, ok := workflowAllowedTagMap[templateTag]; !ok {
|
if _, ok := workflowAllowedTagMap[templateTag]; !ok {
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -109,7 +108,7 @@ func (tagFilter *TagFilter) MatchWithWorkflowTags(templateTags, templateAuthors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsNotEmpty(tagFilter.authors) {
|
if len(tagFilter.authors) > 0 {
|
||||||
for _, templateAuthor := range templateAuthors {
|
for _, templateAuthor := range templateAuthors {
|
||||||
if _, ok := tagFilter.authors[templateAuthor]; !ok {
|
if _, ok := tagFilter.authors[templateAuthor]; !ok {
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -117,7 +116,7 @@ func (tagFilter *TagFilter) MatchWithWorkflowTags(templateTags, templateAuthors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsNotEmpty(tagFilter.severities) {
|
if len(tagFilter.severities) > 0 {
|
||||||
if _, ok := tagFilter.severities[templateSeverity]; !ok {
|
if _, ok := tagFilter.severities[templateSeverity]; !ok {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v2/pkg/parsers"
|
"github.com/projectdiscovery/nuclei/v2/pkg/parsers"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/templates"
|
"github.com/projectdiscovery/nuclei/v2/pkg/templates"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config contains the configuration options for the loader
|
// Config contains the configuration options for the loader
|
||||||
@ -61,7 +60,7 @@ func New(config *Config) (*Store, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle a case with no templates or workflows, where we use base directory
|
// Handle a case with no templates or workflows, where we use base directory
|
||||||
if utils.IsEmpty(config.Templates, config.Workflows) {
|
if len(config.Templates) == 0 && len(config.Workflows) == 0 {
|
||||||
config.Templates = append(config.Templates, config.TemplatesDirectory)
|
config.Templates = append(config.Templates, config.TemplatesDirectory)
|
||||||
}
|
}
|
||||||
store.finalTemplates = append(store.finalTemplates, config.Templates...)
|
store.finalTemplates = append(store.finalTemplates, config.Templates...)
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/internal/severity"
|
"github.com/projectdiscovery/nuclei/v2/internal/severity"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Info struct {
|
type Info struct {
|
||||||
@ -16,12 +17,14 @@ type Info struct {
|
|||||||
SeverityHolder severity.SeverityHolder `yaml:"severity"`
|
SeverityHolder severity.SeverityHolder `yaml:"severity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringSlice represents a single (in-lined) or multiple string value(s).
|
||||||
|
// The unmarshaller does not automatically convert in-lined strings to []string, hence the interface{} type is required.
|
||||||
type StringSlice struct {
|
type StringSlice struct {
|
||||||
Value interface{}
|
Value interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stringSlice *StringSlice) IsEmpty() bool {
|
func (stringSlice *StringSlice) IsEmpty() bool {
|
||||||
return utils.IsEmpty(stringSlice.Value)
|
return len(stringSlice.ToSlice()) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stringSlice StringSlice) ToSlice() []string {
|
func (stringSlice StringSlice) ToSlice() []string {
|
||||||
@ -32,8 +35,9 @@ func (stringSlice StringSlice) ToSlice() []string {
|
|||||||
return value
|
return value
|
||||||
case nil:
|
case nil:
|
||||||
return []string{}
|
return []string{}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Unexpected StringSlice type: '%T'", value))
|
||||||
}
|
}
|
||||||
panic("Illegal State: StringSlice holds non-string value(s)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stringSlice *StringSlice) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (stringSlice *StringSlice) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
@ -44,7 +48,7 @@ func (stringSlice *StringSlice) UnmarshalYAML(unmarshal func(interface{}) error)
|
|||||||
|
|
||||||
result := make([]string, len(marshalledSlice))
|
result := make([]string, len(marshalledSlice))
|
||||||
for _, value := range marshalledSlice {
|
for _, value := range marshalledSlice {
|
||||||
result = append(result, strings.ToLower(strings.TrimSpace(value)))
|
result = append(result, strings.ToLower(strings.TrimSpace(value))) // TODO do we need to introduce RawStringSlice and/or NormalizedStringSlices?
|
||||||
}
|
}
|
||||||
stringSlice.Value = result
|
stringSlice.Value = result
|
||||||
return nil
|
return nil
|
||||||
@ -65,7 +69,7 @@ func marshalStringToSlice(unmarshal func(interface{}) error) ([]string, error) {
|
|||||||
var result []string
|
var result []string
|
||||||
if len(marshalledValuesAsSlice) > 0 {
|
if len(marshalledValuesAsSlice) > 0 {
|
||||||
result = marshalledValuesAsSlice
|
result = marshalledValuesAsSlice
|
||||||
} else if utils.IsNotEmpty(marshalledValueAsString) {
|
} else if utils.IsNotBlank(marshalledValueAsString) {
|
||||||
result = strings.Split(marshalledValueAsString, ",")
|
result = strings.Split(marshalledValueAsString, ",")
|
||||||
} else {
|
} else {
|
||||||
result = []string{}
|
result = []string{}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ func Load(templatePath string, isWorkflow bool, workflowTags []string, tagFilter
|
|||||||
return false, validationError
|
return false, validationError
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsNotEmpty(template.Workflows) {
|
if len(template.Workflows) > 0 {
|
||||||
if isWorkflow {
|
if isWorkflow {
|
||||||
return true, nil // if a workflow is declared and this template is a workflow, then load
|
return true, nil // if a workflow is declared and this template is a workflow, then load
|
||||||
} else { //nolint:indent-error-flow,revive // preferred: readability and extensibility
|
} else { //nolint:indent-error-flow,revive // preferred: readability and extensibility
|
||||||
@ -48,7 +48,7 @@ func isInfoMetadataMatch(tagFilter *filter.TagFilter, templateInfo *model.Info,
|
|||||||
|
|
||||||
var match bool
|
var match bool
|
||||||
var err error
|
var err error
|
||||||
if utils.IsEmpty(workflowTags) {
|
if len(workflowTags) == 0 {
|
||||||
match, err = tagFilter.Match(templateTags, templateAuthors, templateSeverity)
|
match, err = tagFilter.Match(templateTags, templateAuthors, templateSeverity)
|
||||||
} else {
|
} else {
|
||||||
match, err = tagFilter.MatchWithWorkflowTags(templateTags, templateAuthors, templateSeverity, workflowTags)
|
match, err = tagFilter.MatchWithWorkflowTags(templateTags, templateAuthors, templateSeverity, workflowTags)
|
||||||
@ -62,16 +62,15 @@ func isInfoMetadataMatch(tagFilter *filter.TagFilter, templateInfo *model.Info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateMandatoryInfoFields(info *model.Info) error {
|
func validateMandatoryInfoFields(info *model.Info) error {
|
||||||
if utils.IsEmpty(&info) {
|
if &info == nil {
|
||||||
return fmt.Errorf(mandatoryFieldMissingTemplate, "info")
|
return fmt.Errorf(mandatoryFieldMissingTemplate, "info")
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsEmpty(&info.Name) {
|
if utils.IsBlank(info.Name) {
|
||||||
return fmt.Errorf(mandatoryFieldMissingTemplate, "name")
|
return fmt.Errorf(mandatoryFieldMissingTemplate, "name")
|
||||||
}
|
}
|
||||||
|
|
||||||
authors := info.Authors.ToSlice()
|
if info.Authors.IsEmpty() {
|
||||||
if utils.IsEmpty(&authors) {
|
|
||||||
return fmt.Errorf(mandatoryFieldMissingTemplate, "author")
|
return fmt.Errorf(mandatoryFieldMissingTemplate, "author")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -62,7 +62,7 @@ func (i *Exporter) Export(event *output.ResultEvent) error {
|
|||||||
sarifSeverity := getSarifSeverity(event)
|
sarifSeverity := getSarifSeverity(event)
|
||||||
|
|
||||||
var ruleName string
|
var ruleName string
|
||||||
if utils.IsNotEmpty(event.Info.Name) {
|
if utils.IsNotBlank(event.Info.Name) {
|
||||||
ruleName = event.Info.Name
|
ruleName = event.Info.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ func (i *Exporter) Export(event *output.ResultEvent) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ruleDescription string
|
var ruleDescription string
|
||||||
if utils.IsNotEmpty(event.Info.Description) {
|
if utils.IsNotBlank(event.Info.Description) {
|
||||||
ruleDescription = event.Info.Description
|
ruleDescription = event.Info.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Summary returns a formatted built one line summary of the event
|
// Summary returns a formatted built one line summary of the event
|
||||||
@ -125,11 +124,12 @@ func MarkdownDescription(event *output.ResultEvent) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
referenceValue := event.Info.Reference.Value
|
reference := event.Info.Reference
|
||||||
if utils.IsNotEmpty(referenceValue) {
|
if !reference.IsEmpty() {
|
||||||
builder.WriteString("\nReference: \n")
|
builder.WriteString("\nReference: \n")
|
||||||
|
|
||||||
switch value := referenceValue.(type) { // TODO revisit
|
// TODO remove the code duplication: format.go <-> jira.go
|
||||||
|
switch value := reference.Value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if !strings.HasPrefix(value, "-") {
|
if !strings.HasPrefix(value, "-") {
|
||||||
builder.WriteString("- ")
|
builder.WriteString("- ")
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/trackers/github"
|
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/trackers/github"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/trackers/gitlab"
|
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/trackers/gitlab"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/trackers/jira"
|
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/trackers/jira"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options is a configuration file for nuclei reporting module
|
// Options is a configuration file for nuclei reporting module
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/format"
|
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/format"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Integration is a client for a issue tracker integration
|
// Integration is a client for a issue tracker integration
|
||||||
@ -186,11 +185,13 @@ func jiraFormatDescription(event *output.ResultEvent) string {
|
|||||||
builder.WriteString("\n{code}\n")
|
builder.WriteString("\n{code}\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
referenceValue := event.Info.Reference.Value
|
|
||||||
if utils.IsNotEmpty(referenceValue) {
|
reference := event.Info.Reference
|
||||||
|
if !reference.IsEmpty() {
|
||||||
builder.WriteString("\nReference: \n")
|
builder.WriteString("\nReference: \n")
|
||||||
|
|
||||||
switch v := referenceValue.(type) { // TODO revisit
|
// TODO remove the code duplication: format.go <-> jira.go
|
||||||
|
switch v := reference.Value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if !strings.HasPrefix(v, "-") {
|
if !strings.HasPrefix(v, "-") {
|
||||||
builder.WriteString("- ")
|
builder.WriteString("- ")
|
||||||
|
|||||||
@ -39,10 +39,10 @@ func Parse(filePath string, options protocols.ExecuterOptions) (*Template, error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsEmpty(template.Info.Name) {
|
if utils.IsBlank(template.Info.Name) {
|
||||||
return nil, errors.New("no template name field provided")
|
return nil, errors.New("no template name field provided")
|
||||||
}
|
}
|
||||||
if utils.IsEmpty(template.Info.Authors) {
|
if template.Info.Authors.IsEmpty() {
|
||||||
return nil, errors.New("no template author field provided")
|
return nil, errors.New("no template author field provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +52,12 @@ func Parse(filePath string, options protocols.ExecuterOptions) (*Template, error
|
|||||||
options.TemplatePath = filePath
|
options.TemplatePath = filePath
|
||||||
|
|
||||||
// If no requests, and it is also not a workflow, return error.
|
// If no requests, and it is also not a workflow, return error.
|
||||||
if utils.IsEmpty(template.RequestsDNS, template.RequestsHTTP, template.RequestsFile, template.RequestsNetwork, template.RequestsHeadless, template.Workflows) {
|
if len(template.RequestsDNS)+len(template.RequestsHTTP)+len(template.RequestsFile)+len(template.RequestsNetwork)+len(template.RequestsHeadless)+len(template.Workflows) == 0 {
|
||||||
return nil, fmt.Errorf("no requests defined for %s", template.ID)
|
return nil, fmt.Errorf("no requests defined for %s", template.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile the workflow request
|
// Compile the workflow request
|
||||||
if utils.IsNotEmpty(template.Workflows) {
|
if len(template.Workflows) > 0 {
|
||||||
compiled := &template.Workflow
|
compiled := &template.Workflow
|
||||||
|
|
||||||
compileWorkflow(&options, compiled, options.WorkflowLoader)
|
compileWorkflow(&options, compiled, options.WorkflowLoader)
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import (
|
|||||||
"github.com/projectdiscovery/gologger"
|
"github.com/projectdiscovery/gologger"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/model"
|
"github.com/projectdiscovery/nuclei/v2/pkg/model"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/workflows"
|
"github.com/projectdiscovery/nuclei/v2/pkg/workflows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,13 +44,13 @@ func parseWorkflow(workflow *workflows.WorkflowTemplate, options *protocols.Exec
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseWorkflowTemplate parses a workflow template creating an executor
|
// parseWorkflowTemplate parses a workflow template creating an executer
|
||||||
func parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, options *protocols.ExecuterOptions, loader model.WorkflowLoader, noValidate bool) error {
|
func parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, options *protocols.ExecuterOptions, loader model.WorkflowLoader, noValidate bool) error {
|
||||||
var paths []string
|
var paths []string
|
||||||
|
|
||||||
workflowTags := workflow.Tags.ToSlice()
|
workflowTags := workflow.Tags
|
||||||
if utils.IsNotEmpty(workflowTags) {
|
if !workflowTags.IsEmpty() {
|
||||||
paths = loader.ListTags(workflowTags)
|
paths = loader.ListTags(workflowTags.ToSlice())
|
||||||
} else {
|
} else {
|
||||||
paths = loader.ListTemplates([]string{workflow.Template}, noValidate)
|
paths = loader.ListTemplates([]string{workflow.Template}, noValidate)
|
||||||
}
|
}
|
||||||
@ -76,7 +75,7 @@ func parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, options *protoc
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if template.Executer == nil {
|
if template.Executer == nil {
|
||||||
gologger.Warning().Msgf("Could not parse workflow template %s: no executor found\n", path)
|
gologger.Warning().Msgf("Could not parse workflow template %s: no executer found\n", path)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
workflow.Executers = append(workflow.Executers, &workflows.ProtocolExecuterPair{
|
workflow.Executers = append(workflow.Executers, &workflows.ProtocolExecuterPair{
|
||||||
|
|||||||
@ -1,44 +1,13 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isEmpty(value interface{}) bool {
|
func IsBlank(value string) bool {
|
||||||
if value == nil {
|
return strings.TrimSpace(value) == ""
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
reflectValue := reflect.ValueOf(value)
|
|
||||||
actualValueInterface := reflectValue.Interface()
|
|
||||||
|
|
||||||
// nolint:exhaustive //default branch handles other cases
|
|
||||||
switch reflect.TypeOf(value).Kind() {
|
|
||||||
case reflect.String:
|
|
||||||
reflectedValue := actualValueInterface.(string)
|
|
||||||
return strings.TrimSpace(reflectedValue) == ""
|
|
||||||
case reflect.Slice, reflect.Array, reflect.Map:
|
|
||||||
return reflectValue.Len() == 0
|
|
||||||
case reflect.Int32:
|
|
||||||
return IsEmpty(string(actualValueInterface.(rune)))
|
|
||||||
default:
|
|
||||||
if reflectValue.IsZero() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEmpty(value ...interface{}) bool {
|
func IsNotBlank(value string) bool {
|
||||||
for _, current := range value {
|
return !IsBlank(value)
|
||||||
if IsNotEmpty(current) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsNotEmpty(value interface{}) bool {
|
|
||||||
return !isEmpty(value)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
//nolint:scopelint //false-positive
|
|
||||||
func TestIsEmpty(t *testing.T) {
|
|
||||||
testCases := [...][2]interface{}{
|
|
||||||
{"", true},
|
|
||||||
{' ', true},
|
|
||||||
{'\t', true},
|
|
||||||
{'\n', true},
|
|
||||||
{" ", true},
|
|
||||||
{"\n", true},
|
|
||||||
{"\t", true},
|
|
||||||
{0, true},
|
|
||||||
{[]string{}, true},
|
|
||||||
{[0]string{}, true},
|
|
||||||
{[...]string{}, true},
|
|
||||||
{[]int{}, true},
|
|
||||||
{[0]int{}, true},
|
|
||||||
{[...]int{}, true},
|
|
||||||
{interface{}(nil), true},
|
|
||||||
{[]struct{}(nil), true},
|
|
||||||
{[]interface{}(nil), true},
|
|
||||||
{map[string]interface{}{}, true},
|
|
||||||
{nil, true},
|
|
||||||
|
|
||||||
{'a', false},
|
|
||||||
{1, false},
|
|
||||||
{3.14, false},
|
|
||||||
{" test ", false},
|
|
||||||
{[]string{"a"}, false},
|
|
||||||
{[...]string{"a"}, false},
|
|
||||||
{[2]string{"a", "b"}, false},
|
|
||||||
{[]int{1, 2}, false},
|
|
||||||
{[...]int{1, 2}, false},
|
|
||||||
{struct{ a string }{"a"}, false},
|
|
||||||
{&struct{ a string }{"a"}, false},
|
|
||||||
{[]struct{ a string }{{"b"}, {"b"}}, false},
|
|
||||||
{map[string]interface{}{"a": 13}, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
for index, testCase := range testCases {
|
|
||||||
t.Run(fmt.Sprintf("%v # %d", testCase[0], index), func(t *testing.T) {
|
|
||||||
assert.Equal(t, testCase[1], IsEmpty(testCase[0]))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVariadicIsEmpty(t *testing.T) {
|
|
||||||
testVariadicIsEmpty := func(expected bool, value ...interface{}) {
|
|
||||||
t.Run(fmt.Sprintf("%v", value), func(testCase *testing.T) {
|
|
||||||
assert.Equal(testCase, expected, IsEmpty(value...))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
testVariadicIsEmpty(false, [2]int{1, 2}, [0]int{})
|
|
||||||
testVariadicIsEmpty(false, [0]int{}, [2]int{1, 2})
|
|
||||||
testVariadicIsEmpty(false, [0]int{}, " abc ")
|
|
||||||
testVariadicIsEmpty(false, [0]int{}, []string{}, 123)
|
|
||||||
testVariadicIsEmpty(false, [0]int{}, []string{}, []string{"a"})
|
|
||||||
testVariadicIsEmpty(false, [0]int{}, map[string]int{"a": 123}, map[string]interface{}{"b": "c"})
|
|
||||||
|
|
||||||
testVariadicIsEmpty(true, [0]int{}, "")
|
|
||||||
testVariadicIsEmpty(true, [0]int{}, []string{})
|
|
||||||
testVariadicIsEmpty(true, [0]int{}, []string{}, 0)
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user