UNPKG

4.21 kBMarkdownView Raw
1# Security
2
3Executing arbitrary expressions like enabled by the expression parser of
4mathjs involves a risk in general. When you're using mathjs to let users
5execute arbitrary expressions, it's good to take a moment to think about
6possible security and stability implications, especially when running
7the code server side.
8
9## Security risks
10
11A user could try to inject malicious JavaScript code via the expression
12parser. The expression parser of mathjs offers a sandboxed environment
13to execute expressions which should make this impossible. It's possible
14though that there are unknown security vulnerabilities, so it's important
15to be careful, especially when allowing server side execution of
16arbitrary expressions.
17
18The expression parser of mathjs parses the input in a controlled
19way into an expression tree or abstract syntax tree (AST).
20In a "compile" step, it does as much as possible preprocessing on the
21static parts of the expression, and creates a fast performing function
22which can be used to evaluate the expression repeatedly using a
23dynamically passed scope.
24
25The parser actively prevents access to JavaScripts internal `eval` and
26`new Function` which are the main cause of security attacks. Mathjs
27versions 4 and newer does not use JavaScript's `eval` under the hood.
28Version 3 and older did use `eval` for the compile step. This is not
29directly a security issue but results in a larger possible attack surface.
30
31When running a node.js server, it's good to be aware of the different
32types of security risks. The risk whe running inside a browser may be
33limited though it's good to be aware of [Cross side scripting (XSS)](https://www.wikiwand.com/en/Cross-site_scripting) vulnerabilities. A nice overview of
34security risks of a node.js servers is listed in an article [Node.js security checklist](https://blog.risingstack.com/node-js-security-checklist/) by Gergely Nemeth.
35
36### Less vulnerable expression parser
37
38There is a small number of functions which yield the biggest security
39risk in the expression parser:
40
41- `import` and `createUnit` which alter the built-in functionality and
42 allow overriding existing functions and units.
43- `evaluate`, `parse`, `simplify`, and `derivative` which parse arbitrary
44 input into a manipulable expression tree.
45
46To make the expression parser less vulnerable whilst still supporting
47most functionality, these functions can be disabled:
48
49```js
50import { create, all } from 'mathjs'
51
52const math = create(all)
53const limitedEvaluate = math.evaluate
54
55math.import({
56 'import': function () { throw new Error('Function import is disabled') },
57 'createUnit': function () { throw new Error('Function createUnit is disabled') },
58 'evaluate': function () { throw new Error('Function evaluate is disabled') },
59 'parse': function () { throw new Error('Function parse is disabled') },
60 'simplify': function () { throw new Error('Function simplify is disabled') },
61 'derivative': function () { throw new Error('Function derivative is disabled') }
62}, { override: true })
63
64console.log(limitedEvaluate('sqrt(16)')) // Ok, 4
65console.log(limitedEvaluate('parse("2+3")')) // Error: Function parse is disabled
66```
67
68
69### Found a security vulnerability? Please report in private!
70
71You found a security vulnerability? Awesome! We hope you don't have bad
72intentions and want to help fix the issue. Please report the
73vulnerability in a private way by contacting one of the maintainers
74via mail or an other private channel. That way we can work together
75on a fix before sharing the issue with everybody including the bad guys.
76
77## Stability risks
78
79A user could accidentally or on purpose execute a
80heavy expression like creating a huge matrix. That can let the
81JavaScript engine run out of memory or freeze it when the CPU goes
82to 100% for a long time.
83
84To protect against this sort of issue, one can run the expression parser
85in a separate Web Worker or child_process, so it can't affect the
86main process. The workers can be killed when it runs for too
87long or consumes too much memory. A useful library in this regard
88is [workerpool](https://github.com/josdejong/workerpool), which makes
89it easy to manage a pool of workers in both browser and node.js.