Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/protocols/common/expressions/variables.go
2072 views
1
package expressions
2
3
import (
4
"errors"
5
"regexp"
6
"strings"
7
8
"github.com/Knetic/govaluate"
9
"github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl"
10
)
11
12
var (
13
numericalExpressionRegex = regexp.MustCompile(`^[0-9+\-/\W]+$`)
14
unresolvedVariablesRegex = regexp.MustCompile(`(?:%7[B|b]|\{){2}([^}]+)(?:%7[D|d]|\}){2}["'\)\}]*`)
15
)
16
17
// ContainsUnresolvedVariables returns an error with variable names if the passed
18
// input contains unresolved {{<pattern-here>}} variables.
19
func ContainsUnresolvedVariables(items ...string) error {
20
for _, data := range items {
21
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
22
if len(matches) == 0 {
23
return nil
24
}
25
var unresolvedVariables []string
26
for _, match := range matches {
27
if len(match) < 2 {
28
continue
29
}
30
// Skip if the match is an expression
31
if numericalExpressionRegex.MatchString(match[1]) {
32
continue
33
}
34
// or if it contains only literals (can be solved from expression engine)
35
if hasLiteralsOnly(match[1]) {
36
continue
37
}
38
unresolvedVariables = append(unresolvedVariables, match[1])
39
}
40
if len(unresolvedVariables) > 0 {
41
return errors.New("unresolved variables found: " + strings.Join(unresolvedVariables, ","))
42
}
43
}
44
45
return nil
46
}
47
48
// ContainsVariablesWithNames returns an error with variable names if the passed
49
// input contains unresolved {{<pattern-here>}} variables within the provided list
50
func ContainsVariablesWithNames(names map[string]interface{}, items ...string) error {
51
for _, data := range items {
52
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
53
if len(matches) == 0 {
54
return nil
55
}
56
var unresolvedVariables []string
57
for _, match := range matches {
58
if len(match) < 2 {
59
continue
60
}
61
matchName := match[1]
62
// Skip if the match is an expression
63
if numericalExpressionRegex.MatchString(matchName) {
64
continue
65
}
66
// or if it contains only literals (can be solved from expression engine)
67
if hasLiteralsOnly(match[1]) {
68
continue
69
}
70
if _, ok := names[matchName]; !ok {
71
unresolvedVariables = append(unresolvedVariables, matchName)
72
}
73
}
74
if len(unresolvedVariables) > 0 {
75
return errors.New("unresolved variables with values found: " + strings.Join(unresolvedVariables, ","))
76
}
77
}
78
79
return nil
80
}
81
82
// ContainsVariablesWithIgnoreList returns an error with variable names if the passed
83
// input contains unresolved {{<pattern-here>}} other than the ones listed in the ignore list
84
func ContainsVariablesWithIgnoreList(skipNames map[string]interface{}, items ...string) error {
85
var unresolvedVariables []string
86
for _, data := range items {
87
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
88
if len(matches) == 0 {
89
return nil
90
}
91
for _, match := range matches {
92
if len(match) < 2 {
93
continue
94
}
95
matchName := match[1]
96
// Skip if the match is an expression
97
if numericalExpressionRegex.MatchString(matchName) {
98
continue
99
}
100
// or if it contains only literals (can be solved from expression engine)
101
if hasLiteralsOnly(match[1]) {
102
continue
103
}
104
if _, ok := skipNames[matchName]; ok {
105
continue
106
}
107
unresolvedVariables = append(unresolvedVariables, matchName)
108
}
109
}
110
111
if len(unresolvedVariables) > 0 {
112
return errors.New("unresolved variables with values found: " + strings.Join(unresolvedVariables, ","))
113
}
114
115
return nil
116
}
117
118
func hasLiteralsOnly(data string) bool {
119
expr, err := govaluate.NewEvaluableExpressionWithFunctions(data, dsl.HelperFunctions)
120
if err != nil {
121
return false
122
}
123
if expr != nil {
124
_, err = expr.Evaluate(nil)
125
return err == nil
126
}
127
return true
128
}
129
130