Skip to content

Commit f08447c

Browse files
authored
feat: add safe eval for browser and eval option (#185)
BREAKING CHANGE: - Removes `preventEval` property. Prefer `eval: false` instead. - Changed behavior of `eval` property. In the browser, `eval`/`Function` won't be used by default to evaluate expressions. Instead, we'll safely evaluate using a subset of JavaScript. To resume using unsafe eval in the browser, pass in the option `eval: "native"` Also: - feat: add `ignoreEvalErrors` property.
1 parent 324b8e5 commit f08447c

26 files changed

+5279
-1210
lines changed

README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,20 @@ evaluate method (as the first argument) include:
176176
it is necessary to distinguish between a result which is a failure
177177
and one which is an empty array), it is recommended to switch the
178178
default to `false`.
179-
- ***preventEval*** (**default: false**) - Although JavaScript evaluation
180-
expressions are allowed by default, for security reasons (if one is
181-
operating on untrusted user input, for example), one may wish to
182-
set this option to `true` to throw exceptions when these expressions
183-
are attempted.
179+
- ***eval*** (**default: "safe"**) - Script evaluation method.
180+
`safe`: In browser, it will use a minimal scripting engine which doesn't
181+
use `eval` or `Function` and satisfies Content Security Policy. In NodeJS,
182+
it has no effect and is equivalent to native as scripting is safe there.
183+
`native`: uses the native scripting capabilities. i.e. unsafe `eval` or
184+
`Function` in browser and `vm.Script` in nodejs. `false`: Disable JavaScript
185+
evaluation expressions and throw exceptions when these expressions are attempted.
186+
`callback [ (code, context) => value]`: A custom implementation which is called
187+
with `code` and `context` as arguments to return the evaluated value.
188+
`class`: A class which is created with `code` as constructor argument and code
189+
is evaluated by calling `runInNewContext` with `context`.
190+
``
191+
- ***ignoreEvalErrors*** (**default: false**) - Ignore errors encountered during
192+
script evaluation.
184193
- ***parent*** (**default: null**) - In the event that a query could be
185194
made to return the root node, this allows the parent of that root node
186195
to be returned within results.

badges/coverage-badge.svg

Lines changed: 1 addition & 1 deletion
Loading

badges/tests-badge.svg

Lines changed: 1 addition & 1 deletion
Loading

demo/index.html

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,59 @@
99
<body>
1010
<h2>JSONPath Demo <i id="demoNode">(To demo on Node instead, see the <a href="https://npm.runkit.com/jsonpath-plus">library on Runkit</a>.)</i>
1111
</h2>
12-
<form>
12+
<form onsubmit="return false">
1313
<div>
1414
<label><b>JSONPath:</b>
15-
<input id="jsonpath" placeholder="$.books" />
15+
<input type="text" id="jsonpath" placeholder="$.books" value="$..book[?(@parent.bicycle && @parent.bicycle.color === &quot;red&quot;)].category" />
16+
</label>
17+
<label><b>eval:</b>
18+
<select id="eval">
19+
<option value="safe">safe</option>
20+
<option value="native">native</option>
21+
<option value="false">false</option>
22+
</select>
1623
</label>
1724
</div>
1825
<div id="jsonSampleContainer" class="container">
1926
<label><b>JSON sample:</b>
20-
<textarea id="jsonSample" placeholder="{&quot;books&quot;: []}"></textarea>
27+
<textarea id="jsonSample" placeholder="{&quot;books&quot;: []}">
28+
{
29+
"store": {
30+
"book": [
31+
{
32+
"category": "reference",
33+
"author": "Nigel Rees",
34+
"title": "Sayings of the Century",
35+
"price": 8.95
36+
},
37+
{
38+
"category": "fiction",
39+
"author": "Evelyn Waugh",
40+
"title": "Sword of Honour",
41+
"price": 12.99
42+
},
43+
{
44+
"category": "fiction",
45+
"author": "Herman Melville",
46+
"title": "Moby Dick",
47+
"isbn": "0-553-21311-3",
48+
"price": 8.99
49+
},
50+
{
51+
"category": "fiction",
52+
"author": "J. R. R. Tolkien",
53+
"title": "The Lord of the Rings",
54+
"isbn": "0-395-19395-8",
55+
"price": 22.99
56+
}
57+
],
58+
"bicycle": {
59+
"color": "red",
60+
"price": 19.95
61+
}
62+
}
63+
}
64+
</textarea>
2165
</label>
2266
</div>
2367
<div id="resultContainer" class="container">

demo/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ const updateResults = () => {
3333
}
3434
const result = new JSONPath.JSONPath({
3535
path: $('#jsonpath').value,
36-
json
36+
json,
37+
eval: $('#eval').value === 'false' ? false : $('#eval').value
3738
});
3839

3940
$('#results').value = JSON.stringify(result, null, 2);
@@ -46,3 +47,7 @@ $('#jsonpath').addEventListener('input', () => {
4647
$('#jsonSample').addEventListener('input', () => {
4748
updateResults();
4849
});
50+
51+
$('#eval').addEventListener('change', () => {
52+
updateResults();
53+
});

0 commit comments

Comments
 (0)