Skip to content

Commit 1d579db

Browse files
Prevent writing to the object prototype or constructor (v1 port) (#681)
* Prevent access to __proto__ Signed-off-by: andrew-coleman <[email protected]> * Check for constructor property * Adjust for sync --------- Signed-off-by: andrew-coleman <[email protected]> Co-authored-by: andrew-coleman <[email protected]>
1 parent ebdb02a commit 1d579db

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

src/jsonata.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,13 @@ var jsonata = (function() {
12951295
}
12961296
for(var ii = 0; ii < matches.length; ii++) {
12971297
var match = matches[ii];
1298+
if (match && (match.isPrototypeOf(result) || match instanceof Object.constructor)) {
1299+
throw {
1300+
code: "D1010",
1301+
stack: (new Error()).stack,
1302+
position: expr.position
1303+
};
1304+
}
12981305
// evaluate the update value for each match
12991306
var update = yield * evaluate(expr.update, match, environment);
13001307
// update must be an object
@@ -1539,7 +1546,7 @@ var jsonata = (function() {
15391546
if (typeof err.token == 'undefined' && typeof proc.token !== 'undefined') {
15401547
err.token = proc.token;
15411548
}
1542-
err.position = proc.position;
1549+
err.position = proc.position || err.position;
15431550
}
15441551
throw err;
15451552
}
@@ -1971,6 +1978,7 @@ var jsonata = (function() {
19711978
"T1007": "Attempted to partially apply a non-function. Did you mean ${{{token}}}?",
19721979
"T1008": "Attempted to partially apply a non-function",
19731980
"D1009": "Multiple key definitions evaluate to same key: {{value}}",
1981+
"D1010": "Attempted to access the Javascript object prototype", // Javascript specific
19741982
"T1010": "The matcher function argument passed to function {{token}} does not return the correct object structure",
19751983
"T2001": "The left side of the {{token}} operator must evaluate to a number",
19761984
"T2002": "The right side of the {{token}} operator must evaluate to a number",

test/implementation-tests.js

+26
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,32 @@ describe("Tests that are specific to a Javascript runtime", () => {
806806
});
807807
});
808808
});
809+
describe("Expressions that attempt to pollute the object prototype", function() {
810+
it("should throw an error with __proto__", async function() {
811+
const expr = jsonata('{} ~> | __proto__ | {"is_admin": true} |');
812+
expect(function() {
813+
expr.evaluate();
814+
})
815+
.to.throw()
816+
.to.deep.contain({ position: 7, code: "D1010" });
817+
});
818+
it("should throw an error with __lookupGetter__", async function() {
819+
const expr = jsonata('{} ~> | __lookupGetter__("__proto__")() | {"is_admin": true} |');
820+
expect(function() {
821+
expr.evaluate();
822+
})
823+
.to.throw()
824+
.to.deep.contain({ position: 7, code: "D1010" });
825+
});
826+
it("should throw an error with constructor", async function() {
827+
const expr = jsonata('{} ~> | constructor | {"is_admin": true} |');
828+
expect(function() {
829+
expr.evaluate();
830+
})
831+
.to.throw()
832+
.to.deep.contain({ position: 7, code: "D1010" });
833+
});
834+
});
809835
});
810836

811837
describe("Test that yield platform specific results", () => {

0 commit comments

Comments
 (0)