Question

Some claim eval is evil.

Any regular HTML page may look like:

        <script src="some-trendy-js-library.js"></script>
    </body>
</html>

That is, assuming the person doing this knows his job and leaves javascript to load at the end of the page.

Here, we are basically loading a script file into the web browser. Some people have gone deeper and use this as a way to communicate with a 3rd party server...

<script src="//foo.com/bar.js"></script>

At this point, it's been found important to actually load those scripts conditionally at runtime, for whatever reason.

What is my point? While the mechanics differ, we're doing the same thing...executing a piece of plain text as code - aka eval().


Now that I've made my point clear, here goes the question...

Given certain conditions, such as an AJAX request, or (more interestingly) a websocket connection, what is the best way to execute a response from the server?

Here's a couple to get you thinking...

  • eval() the server's output. (did that guy over there just faint?)
  • run a named function returned by the server: var resp = sock.msg; myObj[resp]();
  • build my own parser to figure out what the server is trying to tell me without messing with the javascript directly.
Was it helpful?

Solution

Given certain conditions, such as an AJAX request, or (more interestingly) a websocket connection, what is the best way to execute a response from the server?

The main criticism of eval when used to parse message results is that it is overkill -- you are using a sledgehammer to swat a fly with all the extra risk that comes from overpowered tools -- they can bounce back and hit you.

Let's break the kinds of responses into a few different categories:

  1. Static javascript loaded on demand
  2. A dynamic response from a trusted source on a secure channel that includes no content specified by untrusted parties.
  3. A dynamic response from mixed sources (maybe mostly trusted but includes encoded strings specified by untrusted parties) that is mostly data
  4. Side-effects based on data

For (1), there is no difference between XHR+eval and <script src>, but XHR+eval has few advantages.

For (2), little difference. If you can unpack the response using JSON.parse you are likely to run into fewer problems, but eval's extra authority is less likely to be abused with data from a trusted source than otherwise so not a big deal if you've got a good positive reason for eval.

For (3), there is a big difference. eval's extra-abusable authority is likely to bite you even if you're very careful. This is brittle security-wise. Don't do it.

For (4), it's best if you can separate it into a data problem and a code problem. JSONP allows this if you can validate the result before execution. Parse the data using JSON.parse or something else with little abusable authority, so a function you wrote and approved for external use does the side-effects. This minimizes the excess abusable authority. Naive eval is dangerous here.

OTHER TIPS

"Evil" does not mean "forbidden". Sometimes, there are perfectly good reasons to use so-called "evil" features. They are just called "evil" since they can be, and often are, misused.

In your case, the client-side script is only allowed to make requests to "its own" server. This is the same server the original JavaScript came from, so the dynamic response is as trusted as the original code. A perfectly valid scenario for eval().

If you're fetching code from a domain you don't control, then handing over the code "raw" to the JavaScript interpreter always means you have to completely trust that domain, or else that you have to not care whether malicious code corrupts your own pages.

If you control the domain, then do whatever you want.

The server should provide you with data, not code. You should have the server respond with JSON data that your JS code can act accordingly. Having the server send names of functions to be called with myObj[resp](); is still tightly coupling the server logic with client logic.

It's hard to provide more suggestions without some example code.

Have your server return JSON, and interpret that JSON on the client. The client will figure out what to do with the JSON, just as the server figures out what to do with requests received by the client.

If your server starts returning executable code, you have a problem. NOT because something "bad" is going to happen (although it might), but because your server is not responsible for knowing what the client is or is not suppose to do.

That's like sending code to the server and expected the server to execute it. Unless you've got a REALLY good reason (such as an in-browser IDE), that's a bad idea.

Use eval as much as you want, just make sure you're seperating responsibilites.

Edit:

I see the flaw in this logic. The server is obviously telling the client what to do, simply because it supplied the scripts that the client executes. However, my point is that the server-side code should not be generating scripts on the fly. The server should be orchestrating, not producing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top