Comparing version 10.0.0 to 11.0.0
@@ -7,3 +7,51 @@ # json Changelog | ||
## 11.0.0 | ||
- **Backward incompatible** and **security-related** change to parsing the | ||
`-d DELIM` option. ([#148](https://github.com/trentm/json/issues/148)) | ||
The `-d DELIM` option allows specifying the field delimiter in output: | ||
% echo '{"name":"trent","age":38}' | json -a name age | ||
trent 38 | ||
% echo '{"name":"trent","age":38}' | json -a name age -d, | ||
trent,38 | ||
The given "DELIM" string is parsed to allow escapes. For example: | ||
% echo '{"name":"trent","age":38}' | json -a name age -d'\t' | ||
trent 38 | ||
% echo '{"name":"trent","age":38}' | json -a name age -d'\n' | ||
trent | ||
38 | ||
Before this change, that parsing used `eval()`, which allowed for unintended | ||
code execution if an untrusted argument to `-d` was provided. The fix for | ||
this vulnerability changes to use `JSON.parse()` to support escapes. However | ||
that results in a backward incompatible change, because the set of | ||
[JSON escapes](https://tools.ietf.org/html/rfc7159#section-7) is a *subset* of | ||
[JavaScript escapes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#escape_notation). | ||
The only escape I expect that would affect any current user would be the | ||
null byte escape (`\0`) which can be useful for processing values that may | ||
have spaces or other likely delimiter characters. For example: | ||
# BEFORE | ||
% echo '{"title":"Monsters, Inc.","year":"2001"}' \ | ||
| json -a title year -d'\0' \ | ||
| xargs -0 node -e 'console.log(process.argv)' | ||
[ 'node', 'Monsters, Inc.', '2001\n' ] | ||
# AFTER | ||
% echo '{"title":"Monsters, Inc.","year":"2001"}' | json -a title year -d'\0' | ||
json: error: Unexpected number in JSON at position 2 | ||
One must now use the JSON unicode escape syntax, '\u0000': | ||
% echo '{"title":"Monsters, Inc.","year":"2001"}' \ | ||
| json -a title year -d'\u0000' \ | ||
| xargs -0 node -e 'console.log(process.argv)' | ||
[ 'node', 'Monsters, Inc.', '2001\n' ] | ||
## 10.0.0 | ||
@@ -10,0 +58,0 @@ |
#!/usr/bin/env node | ||
/** | ||
* Copyright 2020 Trent Mick. | ||
* Copyright 2021 Trent Mick. | ||
* Copyright 2020 Joyent Inc. | ||
@@ -11,3 +11,3 @@ * | ||
var VERSION = '10.0.0'; | ||
var VERSION = '11.0.0'; | ||
@@ -126,7 +126,9 @@ var p = console.warn; | ||
* Parse the given string into a JS string. Basically: handle escapes. | ||
* Note that this only handles JSON escapes, which are a subset of all | ||
* JavaScript-supported string escapes. | ||
*/ | ||
function _parseString(s) { | ||
/* JSSTYLED */ | ||
var quoted = '"' + s.replace(/\\"/, '"').replace('"', '\\"') + '"'; | ||
return eval(quoted); | ||
var quoted = '"' + s.replace(/\\"/g, '"').replace(/"/g, '\\"') + '"'; | ||
return JSON.parse(quoted); | ||
} | ||
@@ -137,3 +139,4 @@ | ||
// START json_parse | ||
var json_parse=function(){"use strict";var a,b,c={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:"\n",r:"\r",t:"\t"},d,e=function(b){throw{name:"SyntaxError",message:b,at:a,text:d}},f=function(c){return c&&c!==b&&e("Expected '"+c+"' instead of '"+b+"'"),b=d.charAt(a),a+=1,b},g=function(){var a,c="";b==="-"&&(c="-",f("-"));while(b>="0"&&b<="9")c+=b,f();if(b==="."){c+=".";while(f()&&b>="0"&&b<="9")c+=b}if(b==="e"||b==="E"){c+=b,f();if(b==="-"||b==="+")c+=b,f();while(b>="0"&&b<="9")c+=b,f()}a=+c;if(!isFinite(a))e("Bad number");else return a},h=function(){var a,d,g="",h;if(b==='"')while(f()){if(b==='"')return f(),g;if(b==="\\"){f();if(b==="u"){h=0;for(d=0;d<4;d+=1){a=parseInt(f(),16);if(!isFinite(a))break;h=h*16+a}g+=String.fromCharCode(h)}else if(typeof c[b]=="string")g+=c[b];else break}else g+=b}e("Bad string")},i=function(){while(b&&b<=" ")f()},j=function(){switch(b){case"t":return f("t"),f("r"),f("u"),f("e"),!0;case"f":return f("f"),f("a"),f("l"),f("s"),f("e"),!1;case"n":return f("n"),f("u"),f("l"),f("l"),null}e("Unexpected '"+b+"'")},k,l=function(){var a=[];if(b==="["){f("["),i();if(b==="]")return f("]"),a;while(b){a.push(k()),i();if(b==="]")return f("]"),a;f(","),i()}}e("Bad array")},m=function(){var a,c={};if(b==="{"){f("{"),i();if(b==="}")return f("}"),c;while(b){a=h(),i(),f(":"),Object.hasOwnProperty.call(c,a)&&e('Duplicate key "'+a+'"'),c[a]=k(),i();if(b==="}")return f("}"),c;f(","),i()}}e("Bad object")};return k=function(){i();switch(b){case"{":return m();case"[":return l();case'"':return h();case"-":return g();default:return b>="0"&&b<="9"?g():j()}},function(c,f){var g;return d=c,a=0,b=" ",g=k(),i(),b&&e("Syntax error"),typeof f=="function"?function h(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=h(e,c),d!==undefined?e[c]=d:delete e[c]);return f.call(a,b,e)}({"":g},""):g}}(); | ||
var json_parse=function(){"use strict";var at,ch,escapee={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:"\n",r:"\r",t:"\t"},text,error=function(m){throw{name:"SyntaxError",message:m,at:at,text:text}},next=function(c){if(c&&c!==ch){error("Expected '"+c+"' instead of '"+ch+"'")}ch=text.charAt(at);at+=1;return ch},number=function(){var number,string="";if(ch==="-"){string="-";next("-")}while(ch>="0"&&ch<="9"){string+=ch;next()}if(ch==="."){string+=".";while(next()&&ch>="0"&&ch<="9"){string+=ch}}if(ch==="e"||ch==="E"){string+=ch;next();if(ch==="-"||ch==="+"){string+=ch;next()}while(ch>="0"&&ch<="9"){string+=ch;next()}}number=+string;if(!isFinite(number)){error("Bad number")}else{return number}},string=function(){var hex,i,string="",uffff;if(ch==='"'){while(next()){if(ch==='"'){next();return string}else if(ch==="\\"){next();if(ch==="u"){uffff=0;for(i=0;i<4;i+=1){hex=parseInt(next(),16);if(!isFinite(hex)){break}uffff=uffff*16+hex}string+=String.fromCharCode(uffff)}else if(typeof escapee[ch]==="string"){string+=escapee[ch]}else{break}}else{string+=ch}}}error("Bad string")},white=function(){while(ch&&ch<=" "){next()}},word=function(){switch(ch){case"t":next("t");next("r");next("u");next("e");return true;case"f":next("f");next("a");next("l");next("s");next("e");return false;case"n":next("n");next("u");next("l");next("l");return null}error("Unexpected '"+ch+"'")},value,array=function(){var array=[];if(ch==="["){next("[");white();if(ch==="]"){next("]");return array}while(ch){array.push(value());white();if(ch==="]"){next("]");return array}next(",");white()}}error("Bad array")},object=function(){var key,object={};if(ch==="{"){next("{");white();if(ch==="}"){next("}");return object}while(ch){key=string();white();next(":");if(Object.hasOwnProperty.call(object,key)){error('Duplicate key "'+key+'"')}object[key]=value();white();if(ch==="}"){next("}");return object}next(",");white()}}error("Bad object")};value=function(){white();switch(ch){case"{":return object();case"[":return array();case'"':return string();case"-":return number();default:return ch>="0"&&ch<="9"?number():word()}};return function(source,reviver){var result;text=source;at=0;ch=" ";result=value();white();if(ch){error("Syntax error")}return typeof reviver==="function"?function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}({"":result},""):result}}(); | ||
// END json_parse | ||
@@ -414,3 +417,9 @@ /* END JSSTYLED */ | ||
case '-d': | ||
parsed.delim = _parseString(args.shift()); | ||
var outputDelim = args.shift() | ||
try { | ||
parsed.delim = _parseString(outputDelim); | ||
} catch (parseErr) { | ||
throw new Error(format('could not parse delim "%s": %s', | ||
outputDelim, parseErr.message)); | ||
} | ||
break; | ||
@@ -417,0 +426,0 @@ case '-D': |
{ | ||
"name": "json", | ||
"description": "a 'json' command for massaging and processing JSON on the command line", | ||
"version": "10.0.0", | ||
"version": "11.0.0", | ||
"repository": { | ||
@@ -31,9 +31,9 @@ "type": "git", | ||
"devDependencies": { | ||
"uglify-js": "1.1.x", | ||
"nodeunit": "0.8.x", | ||
"ansidiff": "1.0", | ||
"async": "^3.2.0", | ||
"ben": "0.0.x", | ||
"async": "0.1.22", | ||
"semver": "1.1.0" | ||
"nodeunit": "^0.11.3", | ||
"semver": "^7.3.2", | ||
"uglify-js": "^3.10.2" | ||
} | ||
} |
@@ -33,7 +33,7 @@ `json` is a fast CLI tool for working with JSON. It is a single-file node.js | ||
- filter input JSON (see `-e` and `-c` options) | ||
- fast stream processing | ||
- fast stream processing (see `-ga`) | ||
- JSON validation | ||
- in-place file editing | ||
See <http://trentm.com/json> for full docs and examples as a man page. | ||
See <https://trentm.com/json> for full docs and examples as a man page. | ||
@@ -40,0 +40,0 @@ Follow <a href="https://twitter.com/intent/user?screen_name=trentmick" target="_blank">@trentmick</a> |
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
125306
1686
2