Skip to content

Commit df74ff3

Browse files
authored
fix: enable all template types for template list/display (#6668)
* fix: enable all template types for template list/display When using `-tl` or `-td`, explicitly enable all template types (`code`, `file`, `self-contained`, `global-matchers`, `headless`, `dast`) to ensure all templates are listed w/o requiring extra flags. Signed-off-by: Dwi Siswanto <git@dw1.io> * chore: cleanup messy messy messy Signed-off-by: Dwi Siswanto <git@dw1.io> --------- Signed-off-by: Dwi Siswanto <git@dw1.io>
1 parent fe090d7 commit df74ff3

File tree

8 files changed

+345
-97
lines changed

8 files changed

+345
-97
lines changed

internal/runner/runner.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,6 @@ func New(options *types.Options) (*Runner, error) {
125125
}
126126
}
127127

128-
// if template list or template display is enabled, enable all templates
129-
if options.TemplateList || options.TemplateDisplay {
130-
options.EnableCodeTemplates = true
131-
options.EnableFileTemplates = true
132-
options.EnableSelfContainedTemplates = true
133-
options.EnableGlobalMatchersTemplates = true
134-
}
135-
136128
// check for custom template updates and update if available
137129
ctm, err := customtemplates.NewCustomTemplatesManager(options)
138130
if err != nil {

pkg/catalog/loader/loader.go

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ func New(cfg *Config) (*Store, error) {
205205
templatesFinal = append(templatesFinal, v) // something went wrong, treat it as a file
206206
}
207207
}
208+
208209
cfg.TemplateURLs = remoteTemplates
209210
store.finalTemplates = templatesFinal
210211

@@ -214,6 +215,7 @@ func New(cfg *Config) (*Store, error) {
214215
if err != nil {
215216
return store, err
216217
}
218+
217219
store.finalTemplates = append(store.finalTemplates, remoteTemplates...)
218220
store.finalWorkflows = append(store.finalWorkflows, remoteWorkflows...)
219221
}
@@ -249,14 +251,18 @@ func handleTemplatesEditorURLs(input string) string {
249251
if err != nil {
250252
return input
251253
}
254+
252255
if !strings.HasSuffix(parsed.Hostname(), "cloud.projectdiscovery.io") {
253256
return input
254257
}
258+
255259
if strings.HasSuffix(parsed.Path, ".yaml") {
256260
return input
257261
}
262+
258263
parsed.Path = fmt.Sprintf("%s.yaml", parsed.Path)
259264
finalURL := parsed.String()
265+
260266
return finalURL
261267
}
262268

@@ -266,17 +272,21 @@ func handleTemplatesEditorURLs(input string) string {
266272
func (store *Store) ReadTemplateFromURI(uri string, remote bool) ([]byte, error) {
267273
if stringsutil.HasPrefixAny(uri, httpPrefix, httpsPrefix) && remote {
268274
uri = handleTemplatesEditorURLs(uri)
275+
269276
remoteTemplates, _, err := getRemoteTemplatesAndWorkflows([]string{uri}, nil, store.config.RemoteTemplateDomainList)
270277
if err != nil || len(remoteTemplates) == 0 {
271278
return nil, errkit.Wrapf(err, "Could not load template %s: got %v", uri, remoteTemplates)
272279
}
280+
273281
resp, err := retryablehttp.Get(remoteTemplates[0])
274282
if err != nil {
275283
return nil, err
276284
}
285+
277286
defer func() {
278287
_ = resp.Body.Close()
279288
}()
289+
280290
return io.ReadAll(resp.Body)
281291
} else {
282292
return os.ReadFile(uri)
@@ -396,6 +406,7 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
396406
if templatesCache != nil {
397407
if template, _, _ := templatesCache.Has(templatePath); template != nil {
398408
var metadata *index.Metadata
409+
399410
if store.metadataIndex != nil {
400411
metadata, _ = store.metadataIndex.SetFromTemplate(templatePath, template)
401412
} else {
@@ -413,6 +424,7 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
413424

414425
validPaths[templatePath] = struct{}{}
415426
}
427+
416428
if err != nil {
417429
if strings.Contains(err.Error(), templates.ErrExcluded.Error()) {
418430
stats.Increment(templates.TemplatesExcludedStats)
@@ -421,6 +433,7 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
421433
}
422434
continue
423435
}
436+
424437
store.logger.Warning().Msg(err.Error())
425438
}
426439
}
@@ -431,41 +444,36 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
431444
}
432445

433446
loadedTemplateIDs := mapsutil.NewSyncLockMap[string, struct{}]()
447+
caps := templates.Capabilities{
448+
Headless: store.config.ExecutorOptions.Options.Headless,
449+
Code: store.config.ExecutorOptions.Options.EnableCodeTemplates,
450+
DAST: store.config.ExecutorOptions.Options.DAST,
451+
SelfContained: store.config.ExecutorOptions.Options.EnableSelfContainedTemplates,
452+
File: store.config.ExecutorOptions.Options.EnableFileTemplates,
453+
}
454+
isListOrDisplay := store.config.ExecutorOptions.Options.TemplateList ||
455+
store.config.ExecutorOptions.Options.TemplateDisplay
434456

435457
for templatePath := range validPaths {
436458
template, _, _ := templatesCache.Has(templatePath)
437-
438-
if len(template.RequestsHeadless) > 0 && !store.config.ExecutorOptions.Options.Headless {
439-
continue
440-
}
441-
442-
if len(template.RequestsCode) > 0 && !store.config.ExecutorOptions.Options.EnableCodeTemplates {
443-
continue
444-
}
445-
446-
if template.IsFuzzing() && !store.config.ExecutorOptions.Options.DAST {
459+
if template == nil {
447460
continue
448461
}
449462

450-
if template.SelfContained && !store.config.ExecutorOptions.Options.EnableSelfContainedTemplates {
463+
if !isListOrDisplay && !template.IsEnabledFor(caps) {
451464
continue
452465
}
453466

454-
if template.HasFileProtocol() && !store.config.ExecutorOptions.Options.EnableFileTemplates {
467+
if loadedTemplateIDs.Has(template.ID) {
468+
store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", template.ID, templatePath)
455469
continue
456470
}
457471

458-
if template != nil {
459-
if loadedTemplateIDs.Has(template.ID) {
460-
store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", template.ID, templatePath)
461-
continue
462-
}
463-
464-
_ = loadedTemplateIDs.Set(template.ID, struct{}{})
465-
template.Path = templatePath
466-
store.templates = append(store.templates, template)
467-
}
472+
_ = loadedTemplateIDs.Set(template.ID, struct{}{})
473+
template.Path = templatePath
474+
store.templates = append(store.templates, template)
468475
}
476+
469477
return nil
470478
}
471479

@@ -561,17 +569,20 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string
561569
// areTemplatesValid = false
562570
store.logger.Warning().Msgf("Found duplicate template ID during validation '%s' => '%s': %s\n", templatePath, existingTemplatePath, template.ID)
563571
}
564-
if !isWorkflow && len(template.Workflows) > 0 {
572+
573+
if !isWorkflow && template.HasWorkflows() {
565574
continue
566575
}
567576
}
577+
568578
if isWorkflow {
569579
if !areWorkflowTemplatesValid(store, template.Workflows) {
570580
areTemplatesValid = false
571581
continue
572582
}
573583
}
574584
}
585+
575586
return areTemplatesValid
576587
}
577588

@@ -580,24 +591,29 @@ func areWorkflowTemplatesValid(store *Store, workflows []*workflows.WorkflowTemp
580591
if !areWorkflowTemplatesValid(store, workflow.Subtemplates) {
581592
return false
582593
}
594+
583595
_, err := store.config.Catalog.GetTemplatePath(workflow.Template)
584596
if err != nil {
585597
if isParsingError(store, "Error occurred loading template %s: %s\n", workflow.Template, err) {
586598
return false
587599
}
588600
}
589601
}
602+
590603
return true
591604
}
592605

593606
func isParsingError(store *Store, message string, template string, err error) bool {
594607
if errors.Is(err, templates.ErrExcluded) {
595608
return false
596609
}
610+
597611
if errors.Is(err, templates.ErrCreateTemplateExecutor) {
598612
return false
599613
}
614+
600615
store.logger.Error().Msgf(message, template, err)
616+
601617
return true
602618
}
603619

@@ -617,6 +633,7 @@ func (store *Store) LoadWorkflows(workflowsList []string) []*templates.Template
617633
if err != nil {
618634
store.logger.Warning().Msgf("Could not load workflow %s: %s\n", workflowPath, err)
619635
}
636+
620637
if loaded {
621638
parsed, err := templates.Parse(workflowPath, store.preprocessor, store.config.ExecutorOptions)
622639
if err != nil {
@@ -626,6 +643,7 @@ func (store *Store) LoadWorkflows(workflowsList []string) []*templates.Template
626643
}
627644
}
628645
}
646+
629647
return loadedWorkflows
630648
}
631649

@@ -663,22 +681,24 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
663681
}
664682
}
665683

666-
concurrency := store.config.ExecutorOptions.Options.TemplateLoadingConcurrency
684+
typesOpts := store.config.ExecutorOptions.Options
685+
concurrency := typesOpts.TemplateLoadingConcurrency
667686
if concurrency <= 0 {
668687
concurrency = types.DefaultTemplateLoadingConcurrency
669688
}
689+
670690
wgLoadTemplates, errWg := syncutil.New(syncutil.WithSize(concurrency))
671691
if errWg != nil {
672692
panic("could not create wait group")
673693
}
674694

675-
if store.config.ExecutorOptions.Options.ExecutionId == "" {
676-
store.config.ExecutorOptions.Options.ExecutionId = xid.New().String()
695+
if typesOpts.ExecutionId == "" {
696+
typesOpts.ExecutionId = xid.New().String()
677697
}
678698

679-
dialers := protocolstate.GetDialersWithId(store.config.ExecutorOptions.Options.ExecutionId)
699+
dialers := protocolstate.GetDialersWithId(typesOpts.ExecutionId)
680700
if dialers == nil {
681-
panic("dialers with executionId " + store.config.ExecutorOptions.Options.ExecutionId + " not found")
701+
panic("dialers with executionId " + typesOpts.ExecutionId + " not found")
682702
}
683703

684704
for _, templatePath := range includedTemplates {
@@ -728,18 +748,18 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
728748
}
729749
store.logger.Warning().Msgf("Could not parse template %s: %s\n", templatePath, err)
730750
} else if parsed != nil {
731-
if !parsed.Verified && store.config.ExecutorOptions.Options.DisableUnsignedTemplates {
751+
if !parsed.Verified && typesOpts.DisableUnsignedTemplates {
732752
// skip unverified templates when prompted to
733753
stats.Increment(templates.SkippedUnsignedStats)
734754
return
735755
}
736756

737-
if parsed.SelfContained && !store.config.ExecutorOptions.Options.EnableSelfContainedTemplates {
757+
if parsed.SelfContained && !typesOpts.EnableSelfContainedTemplates {
738758
stats.Increment(templates.ExcludedSelfContainedStats)
739759
return
740760
}
741761

742-
if parsed.HasFileProtocol() && !store.config.ExecutorOptions.Options.EnableFileTemplates {
762+
if parsed.HasFileRequest() && !typesOpts.EnableFileTemplates {
743763
stats.Increment(templates.ExcludedFileStats)
744764
return
745765
}
@@ -751,11 +771,11 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
751771
}
752772
// DAST only templates
753773
// Skip DAST filter when loading auth templates
754-
if store.ID() != AuthStoreId && store.config.ExecutorOptions.Options.DAST {
774+
if store.ID() != AuthStoreId && typesOpts.DAST {
755775
// check if the template is a DAST template
756776
// also allow global matchers template to be loaded
757-
if parsed.IsFuzzing() || parsed.Options.GlobalMatchers != nil && parsed.Options.GlobalMatchers.HasMatchers() {
758-
if len(parsed.RequestsHeadless) > 0 && !store.config.ExecutorOptions.Options.Headless {
777+
if parsed.IsFuzzableRequest() || parsed.IsGlobalMatchersTemplate() {
778+
if parsed.HasHeadlessRequest() && !typesOpts.Headless {
759779
stats.Increment(templates.ExcludedHeadlessTmplStats)
760780
if config.DefaultConfig.LogAllEvents {
761781
store.logger.Print().Msgf("[%v] Headless flag is required for headless template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
@@ -764,27 +784,27 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
764784
loadTemplate(parsed)
765785
}
766786
}
767-
} else if len(parsed.RequestsHeadless) > 0 && !store.config.ExecutorOptions.Options.Headless {
787+
} else if parsed.HasHeadlessRequest() && !typesOpts.Headless {
768788
// donot include headless template in final list if headless flag is not set
769789
stats.Increment(templates.ExcludedHeadlessTmplStats)
770790
if config.DefaultConfig.LogAllEvents {
771791
store.logger.Print().Msgf("[%v] Headless flag is required for headless template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
772792
}
773-
} else if len(parsed.RequestsCode) > 0 && !store.config.ExecutorOptions.Options.EnableCodeTemplates {
793+
} else if parsed.HasCodeRequest() && !typesOpts.EnableCodeTemplates {
774794
// donot include 'Code' protocol custom template in final list if code flag is not set
775795
stats.Increment(templates.ExcludedCodeTmplStats)
776796
if config.DefaultConfig.LogAllEvents {
777797
store.logger.Print().Msgf("[%v] Code flag is required for code protocol template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
778798
}
779-
} else if len(parsed.RequestsCode) > 0 && !parsed.Verified && len(parsed.Workflows) == 0 {
799+
} else if parsed.HasCodeRequest() && !parsed.Verified && !parsed.HasWorkflows() {
780800
// donot include unverified 'Code' protocol custom template in final list
781801
stats.Increment(templates.SkippedCodeTmplTamperedStats)
782802
// these will be skipped so increment skip counter
783803
stats.Increment(templates.SkippedUnsignedStats)
784804
if config.DefaultConfig.LogAllEvents {
785805
store.logger.Print().Msgf("[%v] Tampered/Unsigned template at %v.\n", aurora.Yellow("WRN").String(), templatePath)
786806
}
787-
} else if parsed.IsFuzzing() && !store.config.ExecutorOptions.Options.DAST {
807+
} else if parsed.IsFuzzableRequest() && !typesOpts.DAST {
788808
stats.Increment(templates.ExludedDastTmplStats)
789809
if config.DefaultConfig.LogAllEvents {
790810
store.logger.Print().Msgf("[%v] -dast flag is required for DAST template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
@@ -822,10 +842,11 @@ func IsHTTPBasedProtocolUsed(store *Store) bool {
822842
templates := append(store.Templates(), store.Workflows()...)
823843

824844
for _, template := range templates {
825-
if len(template.RequestsHTTP) > 0 || len(template.RequestsHeadless) > 0 {
845+
if template.HasHTTPRequest() || template.HasHeadlessRequest() {
826846
return true
827847
}
828-
if len(template.Workflows) > 0 {
848+
849+
if template.HasWorkflows() {
829850
if workflowContainsProtocol(template.Workflows) {
830851
return true
831852
}

pkg/protocols/headless/headless.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,8 @@ func (request *Request) Requests() int {
175175
func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) {
176176
r.options.ApplyNewEngineOptions(opts)
177177
}
178+
179+
// HasFuzzing checks if the request has fuzzing rules defined.
180+
func (request *Request) HasFuzzing() bool {
181+
return len(request.Fuzzing) > 0
182+
}

pkg/protocols/http/http.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,3 +544,8 @@ func init() {
544544
func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) {
545545
r.options.ApplyNewEngineOptions(opts)
546546
}
547+
548+
// HasFuzzing indicates whether the request has fuzzing rules defined.
549+
func (request *Request) HasFuzzing() bool {
550+
return len(request.Fuzzing) > 0
551+
}

pkg/templates/compile.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -320,34 +320,34 @@ func (template *Template) compileProtocolRequests(options *protocols.ExecutorOpt
320320
options.IsMultiProtocol = true
321321
}
322322
} else {
323-
if len(template.RequestsDNS) > 0 {
323+
if template.HasDNSRequest() {
324324
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsDNS)...)
325325
}
326-
if len(template.RequestsFile) > 0 {
326+
if template.HasFileRequest() {
327327
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsFile)...)
328328
}
329-
if len(template.RequestsNetwork) > 0 {
329+
if template.HasNetworkRequest() {
330330
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsNetwork)...)
331331
}
332-
if len(template.RequestsHTTP) > 0 {
332+
if template.HasHTTPRequest() {
333333
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsHTTP)...)
334334
}
335-
if len(template.RequestsHeadless) > 0 && options.Options.Headless {
335+
if template.HasHeadlessRequest() && options.Options.Headless {
336336
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsHeadless)...)
337337
}
338-
if len(template.RequestsSSL) > 0 {
338+
if template.HasSSLRequest() {
339339
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsSSL)...)
340340
}
341-
if len(template.RequestsWebsocket) > 0 {
341+
if template.HasWebsocketRequest() {
342342
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsWebsocket)...)
343343
}
344-
if len(template.RequestsWHOIS) > 0 {
344+
if template.HasWHOISRequest() {
345345
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsWHOIS)...)
346346
}
347-
if len(template.RequestsCode) > 0 && options.Options.EnableCodeTemplates {
347+
if template.HasCodeRequest() && options.Options.EnableCodeTemplates {
348348
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsCode)...)
349349
}
350-
if len(template.RequestsJavascript) > 0 {
350+
if template.HasJavascriptRequest() {
351351
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsJavascript)...)
352352
}
353353
}

0 commit comments

Comments
 (0)