sanitize-html 1.11.4 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.npmignore CHANGED
@@ -1,5 +1,6 @@
1
1
  npm-debug.log
2
2
  *.DS_Store
3
3
  node_modules
4
+ dist
4
5
  # We do not commit CSS, only LESS
5
6
  public/css/*.css
package/README.md CHANGED
@@ -22,6 +22,43 @@ HTML comments are not preserved.
22
22
 
23
23
  ## How to use
24
24
 
25
+ ### Browser
26
+
27
+ *Think first: why do you want to use it in the browser?* Remember, *servers must never trust browsers.* You can't sanitize HTML for saving on the server anywhere else but on the server.
28
+
29
+ But, perhaps you'd like to display sanitized HTML immediately in the browser for preview. Or ask the browser to do the sanitization work on every page load. You can if you want to!
30
+
31
+ * Clone repository
32
+ * Run npm install and build / minify:
33
+
34
+ ```bash
35
+ npm install
36
+ npm run minify
37
+ ```
38
+
39
+ You'll find the minified and unminified versions of sanitize-html (with all its dependencies included) in the dist/ directory.
40
+
41
+ Use it in the browser:
42
+
43
+ ```html
44
+ <html>
45
+ <body>
46
+ <script type="text/javascript" src="dist/sanitize-html.js"></script>
47
+ <script type="text/javascript" src="demo.js"></script>
48
+ </body>
49
+ </html>
50
+ ```
51
+
52
+ ```javascript
53
+ var html = "<strong>hello world</strong>";
54
+ console.log(sanitizeHtml(html));
55
+ console.log(sanitizeHtml("<img src=x onerror=alert('img') />"));
56
+ console.log(sanitizeHtml("console.log('hello world')"));
57
+ console.log(sanitizeHtml("<script>alert('hello world')</script>"));
58
+ ```
59
+
60
+ ### Node (Recommended)
61
+
25
62
  Install module from console:
26
63
 
27
64
  ```bash
@@ -77,7 +114,8 @@ allowedAttributes: {
77
114
  selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
78
115
  // URL schemes we permit
79
116
  allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ],
80
- allowedSchemesByTag: {}
117
+ allowedSchemesByTag: {},
118
+ allowProtocolRelative: true
81
119
  ```
82
120
 
83
121
  #### "What if I want to allow all tags or all attributes?"
@@ -184,6 +222,29 @@ simpleTransform(newTag, newAttributes, shouldMerge)
184
222
 
185
223
  The last parameter (`shouldMerge`) is set to `true` by default. When `true`, `simpleTransform` will merge the current attributes with the new ones (`newAttributes`). When `false`, all existing attributes are discarded.
186
224
 
225
+ You can also add or modify the text contents of a tag:
226
+
227
+ ```js
228
+ clean = sanitizeHtml(dirty, {
229
+ transformTags: {
230
+ 'a': function(tagName, attribs) {
231
+ return {
232
+ tagName: 'a',
233
+ text: 'Some text'
234
+ };
235
+ }
236
+ }
237
+ });
238
+ ```
239
+ For example, you could transform a link element with missing anchor text:
240
+ ```js
241
+ <a href="http://somelink.com"></a>
242
+ ```
243
+ To a link with anchor text:
244
+ ```js
245
+ <a href="http://somelink.com">Some text</a>
246
+ ```
247
+
187
248
  ### Filters
188
249
 
189
250
  You can provide a filter function to remove unwanted tags. Let's suppose we need to remove empty `a` tags like:
@@ -279,6 +340,12 @@ allowedSchemesByTag: {
279
340
  }
280
341
  ```
281
342
 
343
+ And you can forbid the use of protocol-relative URLs (starting with `//`) to access another site using the current protocol, which is allowed by default:
344
+
345
+ ```javascript
346
+ allowProtocolRelative: false
347
+ ```
348
+
282
349
  ### Discarding the entire contents of a disallowed tag
283
350
 
284
351
  Normally, with a few exceptions, if a tag is not allowed, all of the text within it is preserved, and so are any allowed tags within it.
@@ -299,6 +366,14 @@ The content still gets escaped properly, with the exception of the `script` and
299
366
 
300
367
  ## Changelog
301
368
 
369
+ 1.14.1: documented `allowProtocolRelative` option. No code changes from 1.14.0, released a few moments ago.
370
+
371
+ 1.14.0: the new `allowProtocolRelative` option, which is set to `true` by default, allows you to decline to accept URLs that start with `//` and thus point to a different host using the current protocol. If you do **not** want to permit this, set this option to `false`. This is fully backwards compatible because the default behavior is to allow them. Thanks to Luke Bernard.
372
+
373
+ 1.13.0: `transformTags` can now add text to an element that initially had none. Thanks to Dushyant Singh.
374
+
375
+ 1.12.0: option to build for browser-side use. Thanks to Michael Blum.
376
+
302
377
  1.11.4: fixed crash when `__proto__` is a tag name. Now using a safe check for the existence of properties in all cases. Thanks to Andrew Krasichkov.
303
378
 
304
379
  Fixed XSS attack vector via `textarea` tags (when explicitly allowed). Decided that `script` (obviously) and `style` (due to its own XSS vectors) cannot realistically be afforded any XSS protection if allowed, unless we add a full CSS parser. Thanks again to Andrew Krasichkov.
@@ -402,5 +477,3 @@ We're rocking our tests and have been working great in production for months, so
402
477
  Feel free to open issues on [github](http://github.com/punkave/sanitize-html).
403
478
 
404
479
  <a href="http://punkave.com/"><img src="https://raw.github.com/punkave/sanitize-html/master/logos/logo-box-builtby.png" /></a>
405
-
406
-
package/index.js CHANGED
@@ -118,6 +118,7 @@ function sanitizeHtml(html, options, _recursing) {
118
118
  stack.push(frame);
119
119
 
120
120
  var skip = false;
121
+ var hasText = frame.text ? true : false;
121
122
  var transformedTag;
122
123
  if (has(transformTagsMap, name)) {
123
124
  transformedTag = transformTagsMap[name](name, attribs);
@@ -190,6 +191,9 @@ function sanitizeHtml(html, options, _recursing) {
190
191
  result += " />";
191
192
  } else {
192
193
  result += ">";
194
+ if (frame.innerText && !hasText && !options.textFilter) {
195
+ result += frame.innerText;
196
+ }
193
197
  }
194
198
  },
195
199
  ontext: function(text) {
@@ -292,7 +296,12 @@ function sanitizeHtml(html, options, _recursing) {
292
296
  // Case insensitive so we don't get faked out by JAVASCRIPT #1
293
297
  var matches = href.match(/^([a-zA-Z]+)\:/);
294
298
  if (!matches) {
295
- // No scheme = no way to inject js (right?)
299
+ // Protocol-relative URL: "//some.evil.com/nasty"
300
+ if (href.match(/^\/\//)) {
301
+ return !options.allowProtocolRelative;
302
+ }
303
+
304
+ // No scheme
296
305
  return false;
297
306
  }
298
307
  var scheme = matches[1].toLowerCase();
@@ -336,7 +345,8 @@ sanitizeHtml.defaults = {
336
345
  selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
337
346
  // URL schemes we permit
338
347
  allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ],
339
- allowedSchemesByTag: {}
348
+ allowedSchemesByTag: {},
349
+ allowProtocolRelative: true
340
350
  };
341
351
 
342
352
  sanitizeHtml.simpleTransform = function(newTagName, newAttribs, merge) {
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "sanitize-html",
3
- "version": "1.11.4",
3
+ "version": "1.14.1",
4
4
  "description": "Clean up user-submitted HTML, preserving whitelisted elements and whitelisted attributes on a per-element basis",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "mocha test/test.js"
7
+ "build": "browserify index.js > dist/sanitize-html.js --standalone 'sanitizeHtml'",
8
+ "minify": "npm run build && uglifyjs dist/sanitize-html.js > dist/sanitize-html.min.js",
9
+ "test": "mocha test/test.js",
10
+ "prebuild": "npm run test && rm -rf dist && mkdir dist"
8
11
  },
9
12
  "repository": {
10
13
  "type": "git",
@@ -24,5 +27,10 @@
24
27
  "htmlparser2": "^3.9.0",
25
28
  "regexp-quote": "0.0.0",
26
29
  "xtend": "^4.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "browserify": "^13.0.1",
33
+ "mocha": "^2.5.3",
34
+ "uglify-js": "^2.6.2"
27
35
  }
28
36
  }
package/test/test.js CHANGED
@@ -144,6 +144,25 @@ describe('sanitizeHtml', function() {
144
144
  }}), '<a href="http://somelink">some_text_need&quot;to&lt;be&gt;filtered</a>');
145
145
  });
146
146
 
147
+ it('should add new text when not initially set and replace attributes when they are changed by transforming function', function () {
148
+ assert.equal(sanitizeHtml('<a href="http://somelink"></a>', { transformTags: {a: function (tagName, attribs) {
149
+ return {
150
+ tagName: tagName,
151
+ attribs: attribs,
152
+ text: 'some new text'
153
+ }
154
+ }}}), '<a href="http://somelink">some new text</a>');
155
+ });
156
+
157
+ it('should preserve text when initially set and replace attributes when they are changed by transforming function', function () {
158
+ assert.equal(sanitizeHtml('<a href="http://somelink">some initial text</a>', { transformTags: {a: function (tagName, attribs) {
159
+ return {
160
+ tagName: tagName,
161
+ attribs: attribs
162
+ }
163
+ }}}), '<a href="http://somelink">some initial text</a>');
164
+ });
165
+
147
166
  it('should skip an empty link', function() {
148
167
  assert.strictEqual(
149
168
  sanitizeHtml('<p>This is <a href="http://www.linux.org"></a><br/>Linux</p>', {
@@ -495,4 +514,22 @@ describe('sanitizeHtml', function() {
495
514
  ), '!<textarea>&lt;/textarea&gt;&lt;svg/onload=prompt`xs`&gt;</textarea>!'
496
515
  );
497
516
  });
517
+ it('should allow protocol relative links by default', function() {
518
+ assert.equal(
519
+ sanitizeHtml('<a href="//cnn.com/example">test</a>'),
520
+ '<a href="//cnn.com/example">test</a>'
521
+ );
522
+ });
523
+ it('should not allow protocol relative links when allowProtocolRelative is false', function() {
524
+ assert.equal(
525
+ sanitizeHtml('<a href="//cnn.com/example">test</a>', { allowProtocolRelative: false }),
526
+ '<a>test</a>'
527
+ );
528
+ });
529
+ it('should still allow regular relative URLs when allowProtocolRelative is false', function() {
530
+ assert.equal(
531
+ sanitizeHtml('<a href="/welcome">test</a>', { allowProtocolRelative: false }),
532
+ '<a href="/welcome">test</a>'
533
+ );
534
+ });
498
535
  });