0

I'm trying to make a generic table-top RPG helper web app. It has to be generic because Wizards of the Coast is very protective of their copyrights. So, in order to avoid cease-and-desists, the system has to be capable of loading arbitrary rules. That said, my buddies and I (along with most any other user) will be using it for D&D.

In D&D, modifiers are based on a character's stats. To get a modifier, you take the stat, subtract 10, divide by 2, and round down.

function getModifier(statValue) {
    return Math.floor((statValue - 10) / 2);
}

My app will be capable to loading a game's rules from a .json file. I want to be able to make this modifier function user-definable. The easiest way would be to just eval() whatever they provide in the .json file, but obviously that's a terrible idea due to security issues.

Unfortunately, I can't think of a simple way to get around this in a secure manner. Obviously I could write my own parser, but that's more complicated than I'd like/am currently capable of.

Ideas?

17
  • 4
    use JSON.parse. JSON does not define functions. Commented May 4, 2015 at 17:43
  • JSON.parse() will take the json file and return a javascript object, right? The getModifier value will then be a string, and I'll need to parse that string in order to get a function. How do I do that in a secure way, since users can input an arbitrary string for this value? Commented May 4, 2015 at 17:47
  • I'm not sure I understand what a modifier is. Can you give a few examples of user-defined modifiers? Commented May 4, 2015 at 17:47
  • 1
    I did a quick google search and found two options - mathjs.org and jsep.from.so Commented May 4, 2015 at 17:54
  • 2
    It appears that SpiderPig has found what you need. Commented May 4, 2015 at 17:55

4 Answers 4

1

I did a quick google search and found two options - http://mathjs.org and http://jsep.from.so

btw. writing your own parser is not that difficult. You may be able to write one that's sufficient for your purpose in less than 100 lines of code

Sign up to request clarification or add additional context in comments.

Comments

1

First, bear in mind that this is all on the client-side. So long as you trust the JSON (it came from your server or it is controlled alongside the application itself), then you can use it. That doesn't completely rule out some trojan inserting malicious rules, but I don't think botnets have learned to play D&D yet.

To literally avoid eval and provide some modicum of security, you can use new Function. It takes a list of argument names followed by the function body, allowing you a large amount of control over how the function is defined and where it can be referenced from. You only need to store the body in the JSON file, allowing you to largely control the parameters and make it difficult to assign to the global scope, minimizing your attack surface (such as it is) quite a lot.

If you want to have fun with this and now your rules will largely be mathematical, you may consider using a tool like pegjs to generate a parser for your rules. Calculators are one of the classic introductions to parsers and compilers, so this could be an opportunity to play with some fun tech. The rules and parsers built by pegjs are very easy to use in a JS project (I have an example using PegJS and ES6 via Babel).

2 Comments

Do functions defined with new Function have access to objects like XHRs and global assignments like $ or jQuery, or only the passed arguments?
They can access those via window.$, but you can try to obfuscate those somewhat (add code to the head of the function that defines them all to null, for example). Still, being client-side, security will never be absolute.
0

There are two options as I see it. One, if you 100% want to define the function in .json, you will need to parse. JSON does not allow functions, so you need to store the function as a string and eval it.

The better way would be to also provide a config.js ability. Perhaps the .json would have a "configUrl": property, and then expose well known apis, eg RPGHelper.setModifer(someFunction) that you can call from inside the config.js file. The user is then free to define whatever arbitrary logic there.

1 Comment

I think the OP's problem is figuring out how to allow function-like definitions while eliminating or sandboxing any bad stuff that could possibly happen in a function defined by another user.
0

One solution to your problem is to use sandboxed iframes (current supported by all major browsers

You run user code on a separate page, with limited priviliges, in such a way that the code does not interfere with the rest of the application. You can communicate with the sandboxed page using postMessage() and window.onmessage.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.