Skip to content

Commit a5df1fc

Browse files
committed
Stricter JSON parsing, for security
1 parent ec4d446 commit a5df1fc

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

src/parser.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@ function lex(text, parseStringsForObjects){
4242
readNumber();
4343
} else if (isIdent(ch)) {
4444
readIdent();
45+
// identifiers can only be if the preceding char was a { or ,
4546
if (was('{,') && json[0]=='{' &&
4647
(token=tokens[tokens.length-1])) {
4748
token.json = token.text.indexOf('.') == -1;
4849
}
4950
} else if (is('(){}[].,;:')) {
50-
tokens.push({index:index, text:ch, json:is('{}[]:,')});
51+
tokens.push({
52+
index:index,
53+
text:ch,
54+
json:(was(':[,') && is('{[')) || is('}]:,')
55+
});
5156
if (is('{[')) json.unshift(ch);
5257
if (is('}]')) json.shift();
5358
index++;

test/JsonSpec.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ describe('json', function(){
151151
expect(function(){fromJson('[].constructor');}).
152152
toThrow(new Error("Parse Error: Token '.' is not valid json at column 3 of expression [[].constructor] starting at [.constructor]."));
153153
});
154+
155+
it('should not allow object dereference', function(){
156+
expect(function(){fromJson('{a:1, b: $location, c:1}');}).toThrow();
157+
expect(function(){fromJson("{a:1, b:[1]['__parent__']['location'], c:1}");}).toThrow();
158+
});
159+
160+
it('should not allow assignments', function(){
161+
expect(function(){fromJson("{a:1, b:[1]=1, c:1}");}).toThrow();
162+
expect(function(){fromJson("{a:1, b:=1, c:1}");}).toThrow();
163+
expect(function(){fromJson("{a:1, b:x=1, c:1}");}).toThrow();
164+
});
165+
154166
});
155167

156168
});

0 commit comments

Comments
 (0)