Javascript Check if it is safe

Asked

Viewed 214 times

2

I would like to create sequenced objects and to set the name of the object, I could only do by function eval(), I found no other alternatives.

They say it is unscrupulous, and subject to attacks. I would like to know , if the code below offers some insecurity to the site.

var obj1 = { but1: { Label: "button1" }, but2: { Label: "button2" }, but3: { Label: "button3" } };

for (i=4;i<=6;i++)
   x = eval("obj1.but" + i + " = {Label:'button"+i+"'};");

If so, what is the safe way to write this code? Thank you.

3 answers

8

You do not need to use Val in this case. You can access a field determined by a string using the operator []

for (var i=4;i<=6;i++){
    obj1["but"+i] = { Label: "button"+i };
}

But in my opinion the best thing would be to put the buttons on an array or a hash table:

var obj1 = {
    buttons: [
        { Label: "button0" },
        { Label: "button1" },
        { Label: "button2" }
    ]
};


for (var i=3;i<=5;i++) {
   obj1.buttons[i] = { Label: "button"+i };
}

As for security, this particular example you used is not insecure as you can ensure that all strings that are passed to Eval are well behaved. The security issue would arise if you passed some value determined by a user of your website into the Eval.

But although the current version is not unsafe I would still not recommend using Val. It is much more complicated than the alternatives, if there is an error during Val the error message and the stack trace are difficult to debug, and Val blocks several compiler optimizations, which makes your program run more slowly. In addition it is quite easy to introduce a security problem by just doing a small accidental modification in the code.

2

This answer is a addendum the response of @hugomg, summarizing the problem of eval is that the types of data that will be executed, in the question the example is not technically insecure, however there is still the problem of performance, in this example I did more similar to the original code, although I agree with the approach of arrays of @hugomg, I kept it so to compare the performance, see for yourself:

  • Function testObject take or arrow the objects like this obj1['but' + i]
  • Function testEval is its original code eval("obj1.but" + i);

The example:

var obj1 = { but1: { Label: "button1" }, but2: { Label: "button2" }, but3: { Label: "button3" } };

function testEval() {
   for (var i=4;i<=6;i++) {
      x = eval("obj1.but" + i + " = {Label:'button"+i+"'};");
   }
}

function testObject() {
   for (var i=4;i<=6;i++) {
      x = obj1['but' + i] = {Label:'button' + i };
   }
}

var d = new Date().getTime();

for (var i=0;i<100000;i++) {
   testEval();
}

console.log("eval:", (new Date().getTime() - d) + "ms");

d = new Date().getTime();

for (var i=0;i<1000;i++) {
   testObject();
}

console.log("object:", (new Date().getTime() - d) + "ms");

Results in Chrome:

  • testEval took ~477ms to complete
  • testObject took ~2ms to complete

In other words, use like this obj1['but' + i] is much more efficient than eval

In firefox the result is much worse with Eval, it takes 6741ms to run the example:

  • Eval: 6741ms
  • Object: 3ms

1

I would like to know , if the code below offers some insecurity to the site.

...

If yes, what is the safe way to write this code ?

You already know that the eval causes the browser to interpret/execute a code in the same scope where it was called: so, "no". The code running next to the client is not able to modify the server, but has access to local declarations, since the global context anyone can quickly modify (now this is if you want to evaluate a string that came from elsewhere).

I’d worry about using eval in this case, since it can shake the performance of a game (for example), both make the browser re-evaluate and execute a code.

The way you used the eval it wasn’t very advantageous, like, you wanted to get a property from obj1 in a more customized way. Assignments also work with (exp)[expParaONomeDaPropriedade] instead of (exp).identificador:

obj1['0']; // o mesmo que obj1[0]
obj1['but1']; // o mesmo que obj1.but1

The difference of using the . is because you are required to use an identifier in several ways currently:

({ 'a': 2 }).\u{61} // 2
({ 'a': 2 }).\u0061 // 2

({ 'B': 5 }).\u0042 // 5
({ 'B': 5 }).B // 5

Remembering that the name of all properties are forced to be strings, except a property with the name of type 'Symbol'...

  • 1

    thank you very much for the clarification.. I will do the tests the way you propose. My precaution was in highlighting security, but how can I also improve performance. I think it feasible to modify. grateful..

Browser other questions tagged

You are not signed in. Login or sign up in order to post.