UNPKG

13.5 kBMarkdownView Raw
1[![NPM version][npm-image]][npm-url]
2[![Node.js CI](https://github.com/leizongmin/js-xss/actions/workflows/nodejs.yml/badge.svg)](https://github.com/leizongmin/js-xss/actions/workflows/nodejs.yml)
3[![Test coverage][coveralls-image]][coveralls-url]
4[![David deps][david-image]][david-url]
5[![node version][node-image]][node-url]
6[![npm download][download-image]][download-url]
7[![npm license][license-image]][download-url]
8
9[npm-image]: https://img.shields.io/npm/v/xss.svg?style=flat-square
10[npm-url]: https://npmjs.org/package/xss
11[coveralls-image]: https://img.shields.io/coveralls/leizongmin/js-xss.svg?style=flat-square
12[coveralls-url]: https://coveralls.io/r/leizongmin/js-xss?branch=master
13[david-image]: https://img.shields.io/david/leizongmin/js-xss.svg?style=flat-square
14[david-url]: https://david-dm.org/leizongmin/js-xss
15[node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square
16[node-url]: http://nodejs.org/download/
17[download-image]: https://img.shields.io/npm/dm/xss.svg?style=flat-square
18[download-url]: https://npmjs.org/package/xss
19[license-image]: https://img.shields.io/npm/l/xss.svg
20
21# Sanitize untrusted HTML (to prevent XSS) with a configuration specified by a Whitelist.
22
23[![Greenkeeper badge](https://badges.greenkeeper.io/leizongmin/js-xss.svg)](https://greenkeeper.io/)
24
25![xss](https://nodei.co/npm/xss.png?downloads=true&stars=true)
26
27---
28
29`xss` is a module used to filter input from users to prevent XSS attacks.
30([What is XSS attack?](http://en.wikipedia.org/wiki/Cross-site_scripting))
31
32**Project Homepage:** http://jsxss.com
33
34**Try Online:** http://jsxss.com/en/try.html
35
36**[中文版文档](https://github.com/leizongmin/js-xss/blob/master/README.zh.md)**
37
38---
39
40## Features
41
42- Specifies HTML tags and their attributes allowed with whitelist
43- Handle any tags or attributes using custom function.
44
45## Reference
46
47- [XSS Filter Evasion Cheat Sheet](https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet)
48- [Data URI scheme](http://en.wikipedia.org/wiki/Data_URI_scheme)
49- [XSS with Data URI Scheme](http://hi.baidu.com/badzzzz/item/bdbafe83144619c199255f7b)
50
51## Benchmark (for references only)
52
53- the xss module: 22.53 MB/s
54- `xss()` function from module `validator@0.3.7`: 6.9 MB/s
55
56For test code please refer to `benchmark` directory.
57
58## They are using xss module
59
60- **nodeclub** - A Node.js bbs using MongoDB - https://github.com/cnodejs/nodeclub
61- **cnpmjs.org** - Private npm registry and web for Enterprise - https://github.com/cnpm/cnpmjs.org
62- **cocalc.com** - Collaborative Calculation and Data Science - https://cocalc.com
63
64## Install
65
66### NPM
67
68```bash
69npm install xss
70```
71
72### Bower
73
74```bash
75bower install xss
76```
77
78Or
79
80```bash
81bower install https://github.com/leizongmin/js-xss.git
82```
83
84## Usages
85
86### On Node.js
87
88```javascript
89var xss = require("xss");
90var html = xss('<script>alert("xss");</script>');
91console.log(html);
92```
93
94### On Browser
95
96Shim mode (reference file `test/test.html`):
97
98```html
99<script src="https://rawgit.com/leizongmin/js-xss/master/dist/xss.js"></script>
100<script>
101 // apply function filterXSS in the same way
102 var html = filterXSS('<script>alert("xss");</scr' + "ipt>");
103 alert(html);
104</script>
105```
106
107AMD mode - shim:
108
109```html
110<script>
111 require.config({
112 baseUrl: "./",
113 paths: {
114 xss: "https://rawgit.com/leizongmin/js-xss/master/dist/xss.js",
115 },
116 shim: {
117 xss: { exports: "filterXSS" },
118 },
119 });
120 require(["xss"], function (xss) {
121 var html = xss('<script>alert("xss");</scr' + "ipt>");
122 alert(html);
123 });
124</script>
125```
126
127**Notes: please don't use the URL https://rawgit.com/leizongmin/js-xss/master/dist/xss.js in production environment.**
128
129## Command Line Tool
130
131### Process File
132
133You can use the xss command line tool to process a file. Usage:
134
135```bash
136xss -i <input_file> -o <output_file>
137```
138
139Example:
140
141```bash
142xss -i origin.html -o target.html
143```
144
145### Active Test
146
147Run the following command, them you can type HTML
148code in the command-line, and check the filtered output:
149
150```bash
151xss -t
152```
153
154For more details, please run `$ xss -h` to see it.
155
156## Custom filter rules
157
158When using the `xss()` function, the second parameter could be used to specify
159custom rules:
160
161```javascript
162options = {}; // Custom rules
163html = xss('<script>alert("xss");</script>', options);
164```
165
166To avoid passing `options` every time, you can also do it in a faster way by
167creating a `FilterXSS` instance:
168
169```javascript
170options = {}; // Custom rules
171myxss = new xss.FilterXSS(options);
172// then apply myxss.process()
173html = myxss.process('<script>alert("xss");</script>');
174```
175
176Details of parameters in `options` would be described below.
177
178### Whitelist
179
180By specifying a `whiteList`, e.g. `{ 'tagName': [ 'attr-1', 'attr-2' ] }`. Tags
181and attributes not in the whitelist would be filter out. For example:
182
183```javascript
184// only tag a and its attributes href, title, target are allowed
185var options = {
186 whiteList: {
187 a: ["href", "title", "target"],
188 },
189};
190// With the configuration specified above, the following HTML:
191// <a href="#" onclick="hello()"><i>Hello</i></a>
192// would become:
193// <a href="#">&lt;i&gt;Hello&lt;/i&gt;</a>
194```
195
196For the default whitelist, please refer `xss.whiteList`.
197
198`allowList` is also supported, and has the same function as `whiteList`.
199
200### Customize the handler function for matched tags
201
202By specifying the handler function with `onTag`:
203
204```javascript
205function onTag(tag, html, options) {
206 // tag is the name of current tag, e.g. 'a' for tag <a>
207 // html is the HTML of this tag, e.g. '<a>' for tag <a>
208 // options is some addition informations:
209 // isWhite boolean, whether the tag is in whitelist
210 // isClosing boolean, whether the tag is a closing tag, e.g. true for </a>
211 // position integer, the position of the tag in output result
212 // sourcePosition integer, the position of the tag in input HTML source
213 // If a string is returned, the current tag would be replaced with the string
214 // If return nothing, the default measure would be taken:
215 // If in whitelist: filter attributes using onTagAttr, as described below
216 // If not in whitelist: handle by onIgnoreTag, as described below
217}
218```
219
220### Customize the handler function for attributes of matched tags
221
222By specifying the handler function with `onTagAttr`:
223
224```javascript
225function onTagAttr(tag, name, value, isWhiteAttr) {
226 // tag is the name of current tag, e.g. 'a' for tag <a>
227 // name is the name of current attribute, e.g. 'href' for href="#"
228 // isWhiteAttr whether the attribute is in whitelist
229 // If a string is returned, the attribute would be replaced with the string
230 // If return nothing, the default measure would be taken:
231 // If in whitelist: filter the value using safeAttrValue as described below
232 // If not in whitelist: handle by onIgnoreTagAttr, as described below
233}
234```
235
236### Customize the handler function for tags not in the whitelist
237
238By specifying the handler function with `onIgnoreTag`:
239
240```javascript
241function onIgnoreTag(tag, html, options) {
242 // Parameters are the same with onTag
243 // If a string is returned, the tag would be replaced with the string
244 // If return nothing, the default measure would be taken (specifies using
245 // escape, as described below)
246}
247```
248
249### Customize the handler function for attributes not in the whitelist
250
251By specifying the handler function with `onIgnoreTagAttr`:
252
253```javascript
254function onIgnoreTagAttr(tag, name, value, isWhiteAttr) {
255 // Parameters are the same with onTagAttr
256 // If a string is returned, the value would be replaced with this string
257 // If return nothing, then keep default (remove the attribute)
258}
259```
260
261### Customize escaping function for HTML
262
263By specifying the handler function with `escapeHtml`. Following is the default
264function **(Modification is not recommended)**:
265
266```javascript
267function escapeHtml(html) {
268 return html.replace(/</g, "&lt;").replace(/>/g, "&gt;");
269}
270```
271
272### Customize escaping function for value of attributes
273
274By specifying the handler function with `safeAttrValue`:
275
276```javascript
277function safeAttrValue(tag, name, value) {
278 // Parameters are the same with onTagAttr (without options)
279 // Return the value as a string
280}
281```
282
283### Customize CSS filter
284
285If you allow the attribute `style`, the value will be processed by [cssfilter](https://github.com/leizongmin/js-css-filter) module. The cssfilter module includes a default css whitelist. You can specify the options for cssfilter module like this:
286
287```javascript
288myxss = new xss.FilterXSS({
289 css: {
290 whiteList: {
291 position: /^fixed|relative$/,
292 top: true,
293 left: true,
294 },
295 },
296});
297html = myxss.process('<script>alert("xss");</script>');
298```
299
300If you don't want to filter out the `style` content, just specify `false` to the `css` option:
301
302```javascript
303myxss = new xss.FilterXSS({
304 css: false,
305});
306```
307
308For more help, please see https://github.com/leizongmin/js-css-filter
309
310### Quick Start
311
312#### Filter out tags not in the whitelist
313
314By using `stripIgnoreTag` parameter:
315
316- `true` filter out tags not in the whitelist
317- `false`: by default: escape the tag using configured `escape` function
318
319Example:
320
321If `stripIgnoreTag = true` is set, the following code:
322
323```html
324code:
325<script>
326 alert(/xss/);
327</script>
328```
329
330would output filtered:
331
332```html
333code:alert(/xss/);
334```
335
336#### Filter out tags and tag bodies not in the whitelist
337
338By using `stripIgnoreTagBody` parameter:
339
340- `false|null|undefined` by default: do nothing
341- `'*'|true`: filter out all tags not in the whitelist
342- `['tag1', 'tag2']`: filter out only specified tags not in the whitelist
343
344Example:
345
346If `stripIgnoreTagBody = ['script']` is set, the following code:
347
348```html
349code:
350<script>
351 alert(/xss/);
352</script>
353```
354
355would output filtered:
356
357```html
358code:
359```
360
361#### Filter out HTML comments
362
363By using `allowCommentTag` parameter:
364
365- `true`: do nothing
366- `false` by default: filter out HTML comments
367
368Example:
369
370If `allowCommentTag = false` is set, the following code:
371
372```html
373code:<!-- something -->
374END
375```
376
377would output filtered:
378
379```html
380code: END
381```
382
383## Examples
384
385### Allow attributes of whitelist tags start with `data-`
386
387```javascript
388var source = '<div a="1" b="2" data-a="3" data-b="4">hello</div>';
389var html = xss(source, {
390 onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
391 if (name.substr(0, 5) === "data-") {
392 // escape its value using built-in escapeAttrValue function
393 return name + '="' + xss.escapeAttrValue(value) + '"';
394 }
395 },
396});
397
398console.log("%s\nconvert to:\n%s", source, html);
399```
400
401Result:
402
403```html
404<div a="1" b="2" data-a="3" data-b="4">hello</div>
405convert to:
406<div data-a="3" data-b="4">hello</div>
407```
408
409### Allow tags start with `x-`
410
411```javascript
412var source = "<x><x-1>he<x-2 checked></x-2>wwww</x-1><a>";
413var html = xss(source, {
414 onIgnoreTag: function (tag, html, options) {
415 if (tag.substr(0, 2) === "x-") {
416 // do not filter its attributes
417 return html;
418 }
419 },
420});
421
422console.log("%s\nconvert to:\n%s", source, html);
423```
424
425Result:
426
427```html
428<x
429 ><x-1>he<x-2 checked></x-2>wwww</x-1
430 ><a>
431 convert to: &lt;x&gt;<x-1>he<x-2 checked></x-2>wwww</x-1><a></a></a
432></x>
433```
434
435### Parse images in HTML
436
437```javascript
438var source =
439 '<img src="img1">a<img src="img2">b<img src="img3">c<img src="img4">d';
440var list = [];
441var html = xss(source, {
442 onTagAttr: function (tag, name, value, isWhiteAttr) {
443 if (tag === "img" && name === "src") {
444 // Use the built-in friendlyAttrValue function to escape attribute
445 // values. It supports converting entity tags such as &lt; to printable
446 // characters such as <
447 list.push(xss.friendlyAttrValue(value));
448 }
449 // Return nothing, means keep the default handling measure
450 },
451});
452
453console.log("image list:\n%s", list.join(", "));
454```
455
456Result:
457
458```html
459image list: img1, img2, img3, img4
460```
461
462### Filter out HTML tags (keeps only plain text)
463
464```javascript
465var source = "<strong>hello</strong><script>alert(/xss/);</script>end";
466var html = xss(source, {
467 whiteList: {}, // empty, means filter out all tags
468 stripIgnoreTag: true, // filter out all HTML not in the whitelist
469 stripIgnoreTagBody: ["script"], // the script tag is a special case, we need
470 // to filter out its content
471});
472
473console.log("text: %s", html);
474```
475
476Result:
477
478```html
479text: helloend
480```
481
482## License
483
484```text
485Copyright (c) 2012-2018 Zongmin Lei(雷宗民) <leizongmin@gmail.com>
486http://ucdok.com
487
488The MIT License
489
490Permission is hereby granted, free of charge, to any person obtaining
491a copy of this software and associated documentation files (the
492"Software"), to deal in the Software without restriction, including
493without limitation the rights to use, copy, modify, merge, publish,
494distribute, sublicense, and/or sell copies of the Software, and to
495permit persons to whom the Software is furnished to do so, subject to
496the following conditions:
497
498The above copyright notice and this permission notice shall be
499included in all copies or substantial portions of the Software.
500
501THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
502EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
503MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
504NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
505LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
506OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
507WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
508```