diff --git a/CHANGELOG b/CHANGELOG index 68201a1..69dfe48 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ *SVN* +* Automatically strip security delimiter comments from JSON strings before evaling them. The default delimiter is '/*-secure- ... */' or you can specify your own with the Prototype.JSONFilter regular expression. If you wrap your JSON response bodies in this delimiter on the server side, rogue external sites can't hijack potentially sensitive data via ', - emptyFunction: function() {}, + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, K: function(x) { return x } } diff --git a/src/string.js b/src/string.js index 96fc361..9f0d1bf 100644 --- a/src/string.js +++ b/src/string.js @@ -163,12 +163,17 @@ Object.extend(String.prototype, { return this.inspect(true); }, + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); try { - if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this))) - return eval('(' + this + ')'); - } catch (e) {} - throw new SyntaxError('Badly formated JSON string: ' + this.inspect()); + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); }, include: function(pattern) { diff --git a/test/unit/string.html b/test/unit/string.html index 6e09746..d46eec9 100644 --- a/test/unit/string.html +++ b/test/unit/string.html @@ -430,7 +430,13 @@ attackTarget = "Not scared!"; assertRaise('SyntaxError', function(){dangerous.evalJSON(true)}); assertEqual("Not scared!", attackTarget); - }} + + assertEqual('hello world!', ('/*-secure-\n' + valid + '\n*/').evalJSON().test); + var temp = Prototype.JSONFilter; + Prototype.JSONFilter = /^\/\*(.*)\*\/$/; // test custom delimiters. + assertEqual('hello world!', ('/*' + valid + '*/').evalJSON().test); + Prototype.JSONFilter = temp; + }} }, 'testlog'); // ]]>