Repository navigation
Expand file tree
/
Copy pathinfo_test.go
More file actions
120 lines (94 loc) · 5.04 KB
/
Copy pathinfo_test.go
File metadata and controls
120 lines (94 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package protocols
import (
"testing"
"github.com/projectdiscovery/nuclei/v3/pkg/model"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/stretchr/testify/require"
)
func TestRenderInfoLeavesStaticInfoAlone(t *testing.T) {
result := &output.ResultEvent{Host: "example.com", Info: model.Info{Description: "Redis is exposed"}}
renderInfo([]*output.ResultEvent{result}, map[string]interface{}{"host": "example.com"})
require.Equal(t, "Redis is exposed", result.Info.Description)
require.Nil(t, result.TemplateInfo)
}
// Braces that fill nothing, like an SSTI payload in the description, leave the
// text static, so it is neither redacted nor moved off the sarif rule.
func TestRenderInfoLeavesUnfilledBracesStatic(t *testing.T) {
result := &output.ResultEvent{Host: "example.com", Info: model.Info{Description: "Send {{7*7}} or {{config}} in the name parameter"}}
renderInfo([]*output.ResultEvent{result}, map[string]interface{}{})
require.Equal(t, "Send {{7*7}} or {{config}} in the name parameter", result.Info.Description)
require.Nil(t, result.TemplateInfo)
}
func TestRenderInfoFillsResultAndEventValues(t *testing.T) {
result := &output.ResultEvent{
Host: "example.com",
Port: "6379",
MatcherName: "auth",
Info: model.Info{
Name: "Redis {{version}}",
Description: "{{matcher-name}} on {{host}}:{{port}}, version {{version}}",
Impact: "{{to_upper(password)}}",
Remediation: "{{credentials}} stays",
},
}
// The event's host is the raw input, while the output reports the hostname.
data := map[string]interface{}{"host": "redis://example.com:6379", "version": "7.2.4", "password": "admin"}
renderInfo([]*output.ResultEvent{result}, data)
require.Equal(t, "auth on example.com:6379, version 7.2.4", result.Info.Description)
require.Equal(t, "ADMIN", result.Info.Impact)
require.Equal(t, "{{credentials}} stays", result.Info.Remediation)
require.Equal(t, "Redis {{version}}", result.Info.Name)
require.Equal(t, "redis://example.com:6379", data["host"])
require.NotNil(t, result.TemplateInfo)
require.Equal(t, "{{matcher-name}} on {{host}}:{{port}}, version {{version}}", result.TemplateInfo.Description)
require.Equal(t, "{{to_upper(password)}}", result.TemplateInfo.Impact)
}
// Info renders like requests do, so the usual nested placeholder idiom and an
// expression spread over lines work too.
func TestRenderInfoFillsNestedAndMultilinePlaceholders(t *testing.T) {
result := &output.ResultEvent{Info: model.Info{
Description: "Authorization: Basic {{base64('{{username}}:{{password}}')}}",
Remediation: "Upgrade from {{join(\", \",\n versions)}}",
}}
renderInfo([]*output.ResultEvent{result}, map[string]interface{}{
"username": "admin", "password": "secret", "versions": []string{"7.2.4", "6.0.9"},
})
require.Equal(t, "Authorization: Basic YWRtaW46c2VjcmV0", result.Info.Description)
require.Equal(t, "Upgrade from 7.2.4, 6.0.9", result.Info.Remediation)
}
// A hyphenated name reads as subtraction inside a helper unless it is bracketed,
// and the general §name§ marker fills like a {{name}} one.
func TestRenderInfoFillsBracketedNamesAndGeneralMarkers(t *testing.T) {
result := &output.ResultEvent{MatcherName: "auth", Info: model.Info{
Description: "{{to_upper([matcher-name])}} matched",
Impact: "default login §username§ accepted",
}}
renderInfo([]*output.ResultEvent{result}, map[string]interface{}{"username": "admin"})
require.Equal(t, "AUTH matched", result.Info.Description)
require.Equal(t, "default login admin accepted", result.Info.Impact)
}
// A failing expression leaves its field as written; the other fields render.
func TestRenderInfoKeepsAFieldWithAFailingExpression(t *testing.T) {
result := &output.ResultEvent{Host: "example.com", Info: model.Info{
Description: "{{host}} {{to_upper(missing)}}",
Impact: "{{host}} is exposed",
}}
renderInfo([]*output.ResultEvent{result}, map[string]interface{}{})
require.Equal(t, "{{host}} {{to_upper(missing)}}", result.Info.Description)
require.Equal(t, "example.com is exposed", result.Info.Impact)
require.Len(t, result.Info.FilledFields(result.TemplateInfo), 1)
}
// A global matcher's event belongs to the template whose response it matched,
// so only the result fields fill its info.
func TestRenderInfoFillsGlobalMatcherInfoFromResultFieldsOnly(t *testing.T) {
result := &output.ResultEvent{Host: "example.com", Info: model.Info{Description: "Leaked {{token}} on {{host}}"}}
renderInfo([]*output.ResultEvent{result}, map[string]interface{}{"global-matchers": true, "token": "origin-template-payload"})
require.Equal(t, "Leaked {{token}} on example.com", result.Info.Description)
}
// Results are built without scan options, so a network helper never runs.
func TestRenderInfoDeniesNetworkHelpers(t *testing.T) {
result := &output.ResultEvent{Host: "example.com", Info: model.Info{Description: "{{host}} resolves to {{resolve(host)}}"}}
renderInfo([]*output.ResultEvent{result}, map[string]interface{}{})
require.Equal(t, "{{host}} resolves to {{resolve(host)}}", result.Info.Description)
require.Nil(t, result.TemplateInfo)
}