@@ -6,64 +6,133 @@ var util = require('@src/lib/svg_text_utils');
6
6
describe ( 'svg+text utils' , function ( ) {
7
7
'use strict' ;
8
8
9
- describe ( 'convertToTspans' , function ( ) {
9
+ describe ( 'convertToTspans should ' , function ( ) {
10
10
11
11
function mockTextSVGElement ( txt ) {
12
12
return d3 . select ( 'body' )
13
13
. append ( 'svg' )
14
14
. attr ( 'id' , 'text' )
15
15
. append ( 'text' )
16
16
. text ( txt )
17
- . call ( util . convertToTspans ) ;
17
+ . call ( util . convertToTspans )
18
+ . attr ( 'transform' , 'translate(50,50)' ) ;
19
+ }
20
+
21
+ function assertAnchorLink ( node , href ) {
22
+ var a = node . select ( 'a' ) ;
23
+
24
+ expect ( a . attr ( 'xlink:href' ) ) . toBe ( href ) ;
25
+ expect ( a . attr ( 'xlink:show' ) ) . toBe ( href === null ? null : 'new' ) ;
26
+ }
27
+
28
+ function assertAnchorAttrs ( node ) {
29
+ var a = node . select ( 'a' ) ;
30
+
31
+ var WHITE_LIST = [ 'xlink:href' , 'xlink:show' , 'style' ] ,
32
+ attrs = listAttributes ( a . node ( ) ) ;
33
+
34
+ // check that no other attribute are found in anchor,
35
+ // which can be lead to XSS attacks.
36
+
37
+ var hasWrongAttr = attrs . some ( function ( attr ) {
38
+ return WHITE_LIST . indexOf ( attr ) === - 1 ;
39
+ } ) ;
40
+
41
+ expect ( hasWrongAttr ) . toBe ( false ) ;
42
+ }
43
+
44
+ function listAttributes ( node ) {
45
+ var items = Array . prototype . slice . call ( node . attributes ) ;
46
+
47
+ var attrs = items . map ( function ( item ) {
48
+ return item . name ;
49
+ } ) ;
50
+
51
+ return attrs ;
18
52
}
19
53
20
54
afterEach ( function ( ) {
21
55
d3 . select ( '#text' ) . remove ( ) ;
22
56
} ) ;
23
57
24
- it ( 'checks for XSS attack in href' , function ( ) {
58
+ it ( 'check for XSS attack in href' , function ( ) {
25
59
var node = mockTextSVGElement (
26
60
'<a href="javascript:alert(\'attack\')">XSS</a>'
27
61
) ;
28
62
29
63
expect ( node . text ( ) ) . toEqual ( 'XSS' ) ;
30
- expect ( node . select ( 'a' ) . attr ( 'xlink:href' ) ) . toBe ( null ) ;
64
+ assertAnchorAttrs ( node ) ;
65
+ assertAnchorLink ( node , null ) ;
31
66
} ) ;
32
67
33
- it ( 'checks for XSS attack in href (with plenty of white spaces)' , function ( ) {
68
+ it ( 'check for XSS attack in href (with plenty of white spaces)' , function ( ) {
34
69
var node = mockTextSVGElement (
35
70
'<a href = " javascript:alert(\'attack\')">XSS</a>'
36
71
) ;
37
72
38
73
expect ( node . text ( ) ) . toEqual ( 'XSS' ) ;
39
- expect ( node . select ( 'a' ) . attr ( 'xlink:href' ) ) . toBe ( null ) ;
74
+ assertAnchorAttrs ( node ) ;
75
+ assertAnchorLink ( node , null ) ;
40
76
} ) ;
41
77
42
- it ( 'whitelists http hrefs' , function ( ) {
78
+ it ( 'whitelist http hrefs' , function ( ) {
43
79
var node = mockTextSVGElement (
44
80
'<a href="http://bl.ocks.org/">bl.ocks.org</a>'
45
81
) ;
46
82
47
83
expect ( node . text ( ) ) . toEqual ( 'bl.ocks.org' ) ;
48
- expect ( node . select ( 'a' ) . attr ( 'xlink:href' ) ) . toEqual ( 'http://bl.ocks.org/' ) ;
84
+ assertAnchorAttrs ( node ) ;
85
+ assertAnchorLink ( node , 'http://bl.ocks.org/' ) ;
49
86
} ) ;
50
87
51
- it ( 'whitelists https hrefs' , function ( ) {
88
+ it ( 'whitelist https hrefs' , function ( ) {
52
89
var node = mockTextSVGElement (
53
90
'<a href="https://plot.ly">plot.ly</a>'
54
91
) ;
55
92
56
93
expect ( node . text ( ) ) . toEqual ( 'plot.ly' ) ;
57
- expect ( node . select ( 'a' ) . attr ( 'xlink:href' ) ) . toEqual ( 'https://plot.ly' ) ;
94
+ assertAnchorAttrs ( node ) ;
95
+ assertAnchorLink ( node , 'https://plot.ly' ) ;
58
96
} ) ;
59
97
60
- it ( 'whitelists mailto hrefs' , function ( ) {
98
+ it ( 'whitelist mailto hrefs' , function ( ) {
61
99
var node = mockTextSVGElement (
62
100
'<a href="mailto:[email protected] ">support</a>'
63
101
) ;
64
102
65
103
expect ( node . text ( ) ) . toEqual ( 'support' ) ;
66
- expect ( node . select ( 'a' ) . attr ( 'xlink:href' ) ) . toEqual ( 'mailto:[email protected] ' ) ;
104
+ assertAnchorAttrs ( node ) ;
105
+ assertAnchorLink ( node , 'mailto:[email protected] ' ) ;
106
+ } ) ;
107
+
108
+ it ( 'wrap XSS attacks in href' , function ( ) {
109
+ var textCases = [
110
+ '<a href="XSS\" onmouseover="alert(1)\" style="font-size:300px">Subtitle</a>' ,
111
+ '<a href="XSS" onmouseover="alert(1)" style="font-size:300px">Subtitle</a>'
112
+ ] ;
113
+
114
+ textCases . forEach ( function ( textCase ) {
115
+ var node = mockTextSVGElement ( textCase ) ;
116
+
117
+ expect ( node . text ( ) ) . toEqual ( 'Subtitle' ) ;
118
+ assertAnchorAttrs ( node ) ;
119
+ assertAnchorLink ( node , 'XSS onmouseover=alert(1) style=font-size:300px' ) ;
120
+ } ) ;
121
+ } ) ;
122
+
123
+ it ( 'should keep query parameters in href' , function ( ) {
124
+ var textCases = [
125
+ '<a href="https://abc.com/myFeature.jsp?name=abc&pwd=def">abc.com?shared-key</a>' ,
126
+ '<a href="https://abc.com/myFeature.jsp?name=abc&pwd=def">abc.com?shared-key</a>'
127
+ ] ;
128
+
129
+ textCases . forEach ( function ( textCase ) {
130
+ var node = mockTextSVGElement ( textCase ) ;
131
+
132
+ assertAnchorAttrs ( node ) ;
133
+ expect ( node . text ( ) ) . toEqual ( 'abc.com?shared-key' ) ;
134
+ assertAnchorLink ( node , 'https://abc.com/myFeature.jsp?name=abc&pwd=def' ) ;
135
+ } ) ;
67
136
} ) ;
68
137
} ) ;
69
138
} ) ;
0 commit comments