-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode_component_escaping_test.go
More file actions
155 lines (142 loc) · 6.21 KB
/
node_component_escaping_test.go
File metadata and controls
155 lines (142 loc) · 6.21 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package gotmx
import (
stringutils "github.com/authentic-devel/gotmx/utils"
"testing"
)
// Tests that attributes and text nodes are escaped if requested, in case they are not escaped yet.
// /No matter whether using a literal, a model path or a golang template
func TestTextIsEscapedIfRequested(t *testing.T) {
data := nodeComponentTestModel{
StringValue: `"&'<>`,
}
template := stringutils.TrimMargin(
`<div data-g-define="my-template">
| These should be escaped by default: ><&'"
| Already escaped stuff should remain untouched: .><&'"
| <div attribute="Value is static and does contain special chars like <>&'"></div>
| <div attribute='[[ .StringValue ]]'></div>
| <div attribute='{{ .StringValue }}'></div>
| <!-- Already escapes should be untouched -->
| <div attribute=""&'<>"></div>
|</div>`)
expectation := stringutils.TrimMargin(
`<div>
| These should be escaped by default: ><&'"
| Already escaped stuff should remain untouched: .><&'"
| <div attribute="Value is static and does contain special chars like <>&'"></div>
| <div attribute=""&'<>"></div>
| <div attribute=""&'<>"></div>
|
| <div attribute=""&'<>"></div>
|</div>`)
parseRenderAndCompareTemplate(nil, template, "my-template", data, expectation, t)
}
// Tests that text nodes are not escaped if not requested.
func TestTextIsNotEscapedIfNotRequested(t *testing.T) {
data := nodeComponentTestModel{
StringValue: `"&'<>`,
}
template := stringutils.TrimMargin(
`<div data-g-define="my-template">
| These should not be escaped: ><&'"
| This actually will be unescaped because during parsing they will be changed to normal characters: ><&'"
| <div attribute="Value is static and does contain special chars like <>&'"></div>
| <div attribute='[[ .StringValue ]]'></div>
| <div attribute='{{ .StringValue }}'></div>
| <!-- Already escapes should be untouched -->
| <div attribute=""&'<>"></div>
|</div>`)
expectation := stringutils.TrimMargin(
`<div>
| These should not be escaped: ><&'"
| This actually will be unescaped because during parsing they will be changed to normal characters: ><&'"
| <div attribute="Value is static and does contain special chars like <>&'"></div>
| <div attribute=""&'<>"></div>
| <div attribute=""&'<>"></div>
|
| <div attribute=""&'<>"></div>
|</div>`)
parseRenderAndCompareTemplateUnescaped(nil, template, "my-template", data, expectation, t)
}
// Tests, that the content of a g-outer-text attribute is escaped.
func TestGOuterTextIsEscapedIfRequested(t *testing.T) {
data := nodeComponentTestModel{
StringValue: `"&'<>`,
}
template := stringutils.TrimMargin(
`<div data-g-define="my-template">
| <div g-outer-text='{{ .StringValue }}'></div>
| <div g-outer-text='[[ .StringValue ]]'></div>
| <div g-outer-text="<>&'"></div>
|</div>`)
expectation := stringutils.TrimMargin(
`<div>
| "&'<>
| "&'<>
| <>&'
|</div>`)
parseRenderAndCompareTemplate(nil, template, "my-template", data, expectation, t)
}
// Tests that g-outer-text respects the Unescaped() option.
// g-outer-text follows ctx.Escaped since it replaces entire elements and is used
// for raw text extraction (e.g., template references rendered to strings).
func TestGOuterTextIsNotEscapedIfNotRequested(t *testing.T) {
data := nodeComponentTestModel{
StringValue: `"&'<>`,
}
template := stringutils.TrimMargin(
`<div data-g-define="my-template">
| <div g-outer-text='{{ .StringValue }}'></div>
| <div g-outer-text='[[ .StringValue ]]'></div>
| <div g-outer-text="<>&'"></div>
|</div>`)
expectation := stringutils.TrimMargin(
`<div>
| "&'<>
| "&'<>
| <>&'
|</div>`)
parseRenderAndCompareTemplateUnescaped(nil, template, "my-template", data, expectation, t)
}
// Tests, that the content of a g-inner-text attribute is escaped even when the attribute value does not contain a model
// path or go template expression.
func TestGInnerTextIsEscapedIfRequested(t *testing.T) {
data := nodeComponentTestModel{
StringValue: `"&'<>`,
}
template := stringutils.TrimMargin(
`<div data-g-define="my-template">
| <div g-inner-text='{{ .StringValue }}'></div>
| <div g-inner-text='[[ .StringValue ]]'></div>
| <div g-inner-text="<>&'"></div>
|</div>`)
expectation := stringutils.TrimMargin(
`<div>
| <div>"&'<></div>
| <div>"&'<></div>
| <div><>&'</div>
|</div>`)
parseRenderAndCompareTemplate(nil, template, "my-template", data, expectation, t)
}
// Tests that g-inner-text always escapes for XSS safety, even with Unescaped().
// This is an intentional security property: g-inner-text is the safe text injection attribute.
// Use g-inner-html for raw HTML injection of trusted content.
func TestGInnerTextAlwaysEscapesEvenWhenUnescaped(t *testing.T) {
data := nodeComponentTestModel{
StringValue: `"&'<>`,
}
template := stringutils.TrimMargin(
`<div data-g-define="my-template">
| <div g-inner-text='{{ .StringValue }}'></div>
| <div g-inner-text='[[ .StringValue ]]'></div>
| <div g-inner-text="<>&'"></div>
|</div>`)
// Even with Unescaped(), g-inner-text still escapes (security)
expectation := stringutils.TrimMargin(
`<div>
| <div>"&'<></div>
| <div>"&'<></div>
| <div><>&'</div>
|</div>`)
parseRenderAndCompareTemplateUnescaped(nil, template, "my-template", data, expectation, t)
}