2021-07-12 17:20:01 +03:00
package model
import (
2021-08-17 13:46:53 +03:00
"encoding/json"
2021-08-03 14:51:34 +03:00
"fmt"
2021-07-19 21:04:08 +03:00
"strings"
2021-08-23 23:50:45 +05:30
"github.com/alecthomas/jsonschema"
2021-07-16 17:28:13 +03:00
"github.com/projectdiscovery/nuclei/v2/internal/severity"
2021-08-03 15:39:15 +03:00
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
2021-07-12 17:20:01 +03:00
)
2021-08-20 15:11:19 +05:30
// Info contains metadata information about a template
2021-07-12 17:20:01 +03:00
type Info struct {
2021-08-20 15:11:19 +05:30
// description: |
// Name should be good short summary that identifies what the template does.
//
// examples:
// - value: "\"bower.json file disclosure\""
// - value: "\"Nagios Default Credentials Check\""
2021-08-23 23:50:45 +05:30
Name string ` json:"name,omitempty" yaml:"name,omitempty" jsonschema:"title=name of the template,description=Name is a short summary of what the template does,example=Nagios Default Credentials Check" `
2021-08-20 15:11:19 +05:30
// description: |
// Author of the template.
//
2021-09-01 15:08:46 +05:30
// Multiple values can also be specified separated by commas.
2021-08-20 15:11:19 +05:30
// examples:
// - value: "\"<username>\""
2021-08-23 23:50:45 +05:30
Authors StringSlice ` json:"author,omitempty" yaml:"author,omitempty" jsonschema:"title=author of the template,description=Author is the author of the template,example=username" `
2021-08-20 15:11:19 +05:30
// description: |
// Any tags for the template.
//
// Multiple values can also be specified separated by commas.
//
// examples:
// - name: Example tags
// value: "\"cve,cve2019,grafana,auth-bypass,dos\""
2021-08-23 23:50:45 +05:30
Tags StringSlice ` json:"tags,omitempty" yaml:"tags,omitempty" jsonschema:"title=tags of the template,description=Any tags for the template" `
2021-08-20 15:11:19 +05:30
// description: |
// Description of the template.
//
// You can go in-depth here on what the template actually does.
//
// examples:
// - value: "\"Bower is a package manager which stores packages informations in bower.json file\""
// - value: "\"Subversion ALM for the enterprise before 8.8.2 allows reflected XSS at multiple locations\""
2021-08-23 23:50:45 +05:30
Description string ` json:"description,omitempty" yaml:"description,omitempty" jsonschema:"title=description of the template,description=In-depth explanation on what the template does,example=Bower is a package manager which stores packages informations in bower.json file" `
2021-08-20 15:11:19 +05:30
// description: |
// References for the template.
//
// This should contain links relevant to the template.
//
// examples:
// - value: >
// []string{"https://github.com/strapi/strapi", "https://github.com/getgrav/grav"}
2021-08-23 23:50:45 +05:30
Reference StringSlice ` json:"reference,omitempty" yaml:"reference,omitempty" jsonschema:"title=references for the template,description=Links relevant to the template" `
2021-08-20 15:11:19 +05:30
// description: |
// Severity of the template.
//
// values:
// - info
// - low
// - medium
// - high
// - critical
SeverityHolder severity . SeverityHolder ` json:"severity,omitempty" yaml:"severity,omitempty" `
2021-08-20 15:13:22 +05:30
// description: |
// AdditionalFields regarding metadata of the template.
//
// examples:
// - value: >
// map[string]string{"customField1":"customValue1"}
2021-08-23 23:50:45 +05:30
AdditionalFields map [ string ] string ` json:"additional-fields,omitempty" yaml:"additional-fields,omitempty" jsonschema:"title=additional metadata for the template,description=Additional metadata fields for the template" `
2021-07-12 17:20:01 +03:00
}
2021-08-03 14:51:34 +03:00
// 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.
2021-07-12 17:20:01 +03:00
type StringSlice struct {
Value interface { }
}
2021-08-23 23:50:45 +05:30
func ( stringSlice StringSlice ) JSONSchemaType ( ) * jsonschema . Type {
gotType := & jsonschema . Type {
OneOf : [ ] * jsonschema . Type { { Type : "string" } , { Type : "array" } } ,
}
return gotType
}
2021-07-12 17:20:01 +03:00
func ( stringSlice * StringSlice ) IsEmpty ( ) bool {
2021-08-03 14:51:34 +03:00
return len ( stringSlice . ToSlice ( ) ) == 0
2021-07-12 17:20:01 +03:00
}
func ( stringSlice StringSlice ) ToSlice ( ) [ ] string {
switch value := stringSlice . Value . ( type ) {
case string :
return [ ] string { value }
case [ ] string :
return value
2021-07-15 13:41:41 +03:00
case nil :
return [ ] string { }
2021-08-03 14:51:34 +03:00
default :
panic ( fmt . Sprintf ( "Unexpected StringSlice type: '%T'" , value ) )
2021-07-12 17:20:01 +03:00
}
}
2021-08-18 18:37:43 +03:00
func ( stringSlice StringSlice ) String ( ) string {
return strings . Join ( stringSlice . ToSlice ( ) , ", " )
}
2021-07-12 17:20:01 +03:00
func ( stringSlice * StringSlice ) UnmarshalYAML ( unmarshal func ( interface { } ) error ) error {
2021-07-15 13:41:41 +03:00
marshalledSlice , err := marshalStringToSlice ( unmarshal )
2021-07-12 17:20:01 +03:00
if err != nil {
2021-07-15 13:41:41 +03:00
return err
2021-07-12 17:20:01 +03:00
}
2021-08-18 18:37:43 +03:00
result := make ( [ ] string , 0 , len ( marshalledSlice ) )
2021-08-03 15:39:15 +03:00
//nolint:gosimple,nolintlint //cannot be replaced with result = append(result, slices...) because the values are being normalized
2021-07-15 13:41:41 +03:00
for _ , value := range marshalledSlice {
2021-08-03 14:51:34 +03:00
result = append ( result , strings . ToLower ( strings . TrimSpace ( value ) ) ) // TODO do we need to introduce RawStringSlice and/or NormalizedStringSlices?
2021-07-12 17:20:01 +03:00
}
stringSlice . Value = result
return nil
}
2021-07-15 13:41:41 +03:00
func marshalStringToSlice ( unmarshal func ( interface { } ) error ) ( [ ] string , error ) {
var marshalledValueAsString string
var marshalledValuesAsSlice [ ] string
sliceMarshalError := unmarshal ( & marshalledValuesAsSlice )
if sliceMarshalError != nil {
stringMarshalError := unmarshal ( & marshalledValueAsString )
if stringMarshalError != nil {
return nil , stringMarshalError
}
}
var result [ ] string
if len ( marshalledValuesAsSlice ) > 0 {
result = marshalledValuesAsSlice
2021-08-03 14:51:34 +03:00
} else if utils . IsNotBlank ( marshalledValueAsString ) {
2021-07-15 13:41:41 +03:00
result = strings . Split ( marshalledValueAsString , "," )
} else {
result = [ ] string { }
}
return result , nil
}
2021-07-12 17:20:01 +03:00
func ( stringSlice StringSlice ) MarshalYAML ( ) ( interface { } , error ) {
2021-08-20 15:11:19 +05:30
return stringSlice . Value , nil
2021-08-17 13:46:53 +03:00
}
func ( stringSlice StringSlice ) MarshalJSON ( ) ( [ ] byte , error ) {
return json . Marshal ( stringSlice . Value )
2021-07-12 17:20:01 +03:00
}