1 | var assert = require("chai").assert;
|
2 | var Linter = require("../linter");
|
3 | var Config = require("../config");
|
4 | var XSSLint = require("../main");
|
5 |
|
6 | function lint(source) {
|
7 | var linter = new Linter(source, XSSLint.config)
|
8 | return linter.run();
|
9 | }
|
10 |
|
11 | describe("Linter", function() {
|
12 | describe("comment directives", function() {
|
13 | it("should be evaluated", function() {
|
14 | var linter = new Linter("//xsslint safeString.identifier foo /bar/");
|
15 | assert.deepEqual(
|
16 | linter.config.properties["safeString.identifier"],
|
17 | [{identifier: "foo"}, {identifier: /bar/}]
|
18 | );
|
19 | });
|
20 |
|
21 | it("should augment existing settings", function() {
|
22 | var config = new Config;
|
23 | config.set("safeString.identifier", "foo");
|
24 | var linter = new Linter("//xsslint safeString.identifier bar", config);
|
25 | assert.deepEqual(
|
26 | linter.config.properties["safeString.identifier"],
|
27 | [{identifier: "foo"}, {identifier: "bar"}]
|
28 | );
|
29 | });
|
30 |
|
31 | it("should replace existing settings if set with a !", function() {
|
32 | var config = new Config;
|
33 | config.set("!safeString.identifier", "foo");
|
34 | var linter = new Linter("//xsslint safeString.identifier bar", config);
|
35 | assert.deepEqual(
|
36 | linter.config.properties["safeString.identifier"],
|
37 | [{identifier: "bar"}]
|
38 | );
|
39 | });
|
40 | });
|
41 |
|
42 | describe("multiple arguments", function() {
|
43 | it("should check all of them", function() {
|
44 | assert.lengthOf(lint("foo.html('ok', 'ok')"), 0);
|
45 | assert.lengthOf(lint("foo.html('ok', 'ok', notOk)"), 1);
|
46 | });
|
47 | });
|
48 |
|
49 | describe("arrays", function() {
|
50 | it("should check each element", function() {
|
51 | assert.lengthOf(lint("foo.html(['ok', 'ok'])"), 0);
|
52 | assert.lengthOf(lint("foo.html(['ok', 'ok', notOk])"), 1);
|
53 | });
|
54 | });
|
55 |
|
56 | describe("logical expressions", function() {
|
57 | it("should check both sides", function() {
|
58 | assert.lengthOf(lint("foo.html('foo' || 'bar')"), 0);
|
59 | assert.lengthOf(lint("foo.html('foo' || 'bar')"), 0);
|
60 | assert.lengthOf(lint("foo.html(foo || 'bar')"), 1);
|
61 | assert.lengthOf(lint("foo.html('foo' || bar)"), 1);
|
62 | });
|
63 | });
|
64 |
|
65 | describe("ternary expressions", function() {
|
66 | it("should check both possibilities", function() {
|
67 | assert.lengthOf(lint("foo.html(orly ? 'foo' : 'bar')"), 0);
|
68 | assert.lengthOf(lint("foo.html(orly ? foo : 'bar')"), 1);
|
69 | assert.lengthOf(lint("foo.html(orly ? 'foo' : bar)"), 1);
|
70 | });
|
71 | });
|
72 |
|
73 | describe("assignment expressions", function() {
|
74 | it("should check the right hand side", function() {
|
75 | assert.lengthOf(lint("foo.html(foo = 'bar')"), 0);
|
76 | assert.lengthOf(lint("foo.html(foo = bar)"), 1);
|
77 | });
|
78 | });
|
79 |
|
80 | describe("strings", function() {
|
81 | describe("literals", function() {
|
82 | it("should be ok", function() {
|
83 | assert.lengthOf(lint("foo.html('ohai')"), 0);
|
84 | });
|
85 | });
|
86 |
|
87 | describe("concatenation", function() {
|
88 | it("should accept safe strings", function() {
|
89 | assert.lengthOf(lint("foo.html('ohai ' + 'you')"), 0);
|
90 | });
|
91 |
|
92 | it("should reject unsafe strings", function() {
|
93 | assert.lengthOf(lint("foo.html('ohai ' + unsafe)"), 1);
|
94 | });
|
95 |
|
96 | it("should reject unsafe strings as part of a standalone html snippet", function() {
|
97 | assert.lengthOf(lint("var foo = '<b>' + unsafe + '</b>'"), 1);
|
98 | assert.lengthOf(lint("var foo = '<b>' + ' ' + unsafe + ' ' + '</b>'"), 1);
|
99 | assert.lengthOf(lint("var foo = unsafe + ' ' + '<img>'"), 1);
|
100 | assert.lengthOf(lint("var foo = '<img>' + ' ' + unsafe"), 1);
|
101 | assert.lengthOf(lint("var foo = '<img>' + (' ' + unsafe)"), 1);
|
102 | });
|
103 | });
|
104 | });
|
105 |
|
106 | describe("jQuery objects", function() {
|
107 | it("should be ok", function() {
|
108 | assert.lengthOf(lint("foo.html($('div'))"), 0);
|
109 | });
|
110 |
|
111 | it("should evaluate method chains", function() {
|
112 | assert.lengthOf(lint("foo.html($('div').clone().hide())"), 0);
|
113 | assert.lengthOf(lint("foo.html(unknown.clone().hide())"), 1);
|
114 | });
|
115 | });
|
116 |
|
117 | describe("$()", function() {
|
118 | it("should allow functions", function() {
|
119 | assert.lengthOf(lint("$(function(){})"), 0);
|
120 | });
|
121 |
|
122 | it("should allow things that look safe", function() {
|
123 | assert.lengthOf(lint("$(template)"), 0);
|
124 | assert.lengthOf(lint("$(template())"), 0);
|
125 | assert.lengthOf(lint("$(this)"), 0);
|
126 | assert.lengthOf(lint("$(this.el)"), 0);
|
127 | });
|
128 |
|
129 | it("should check for unsafe string concatenation", function() {
|
130 | assert.lengthOf(lint("$('<b>' + unknown + '</b>')"), 1);
|
131 | });
|
132 |
|
133 | it("should allow arbitrary concatenation if it seems like a selector", function() {
|
134 | assert.lengthOf(lint("$('.foo_' + unknown)"), 0);
|
135 | assert.lengthOf(lint("$(selectorPrefix + unknown)"), 0);
|
136 | });
|
137 |
|
138 | it("should validate the html attribute", function() {
|
139 | assert.lengthOf(lint("$('<div />', {html: 'ohai'})"), 0);
|
140 | assert.lengthOf(lint("$('<div />', {html: unsafe})"), 1);
|
141 | });
|
142 | });
|
143 | });
|