3

Is this safe? Or will this be vulnerable to code injections?

$scope.placeholder = function(value, def) {
    var val = eval("$rootScope.master.user." + value);
    if (val) {
        return val;
    } else {
        return def;
    }
};

I was using bracket notation, but I realized I could not if I passed in an object such as Address.addr1 in the example below:

<input type="email" ng-model="user.email"  placeholder="{{placeholder('email', 'Email...')}}" /><br/>
<input type="text" ng-model="user.Address.addr1"  placeholder="{{placeholder('Address.addr1', 'Addr. Line 1...')}}" />

I thought this might answer my question, but I wasn't sure: Is using javascript eval() safe for simple calculations in inputs?

Community
  • 1
  • 1
user1791914
  • 616
  • 9
  • 23
  • You can surely use `user.Address.addr1`? How are you suing it? – Satpal Feb 14 '15 at 15:58
  • 1
    This question, especially with the answer, edits, and comments, smells of the XY problem. http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378. Something isn't adding up here, but we don't know enough about the problem domain to understand why you think you need to do something so unorthodox. – Claies Feb 14 '15 at 16:00
  • The bracket notation will still work, but you need to add some additional logic. Something like in this [answer](http://stackoverflow.com/a/10799923/1960455) to the question [Multiple level attribute retrieval using array notation from a JSON object](http://stackoverflow.com/q/10799428/1960455) – t.niese Feb 14 '15 at 16:14
  • I admit, I think I am falling into the XY problem here. The real problem: I need to create an input placeholder that shows either 1) a value, if that value exists in the $rootScope, or 2) a default value if that $rootScope value is not set. My failed solution was the function(in my question), which failed if I tried to use bracket notation and was simply bad practice if I tried to use eval(). I'll look for a better approach altogether. Thanks for the suggestions and keeping me in check with XY. – user1791914 Feb 14 '15 at 16:16

2 Answers2

2

You can simply use Bracket notation.

var val = $rootScope.master.user[value];

You don't need eval for sure. You should read Why is using the JavaScript eval function a bad idea?

Community
  • 1
  • 1
Satpal
  • 132,252
  • 13
  • 159
  • 168
  • I would add that, yes, the OP's code would have been vulnerable to injection, but there is such a thing as $eval and $evalAsync in Angular (neither of which are needed here of course), These are for evaluating "angular expressions": https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$eval – Semicolon Feb 14 '15 at 15:54
  • I just updated my question to give some more context. Bracket notation would work great, but I'm trying to pass in a reference to an object within an object in some instances. – user1791914 Feb 14 '15 at 15:58
2

Is there any reason why you can't do this? Your question does smell of the XY problem, as Claies says:

<input type="email" ng-model="user.email"  
       placeholder="{{ user.email || 'Email...'}}" /><br/>
<input type="text" ng-model="user.Address.addr1"  
        placeholder="{{ user.Address.addr1 || 'Addr. Line 1...'}}" />

Or better yet, the question remains why you are trying to do this at all. A placeholder only has any purpose when the field is blank, so just supply a static value:

<input type="email" ng-model="user.email" placeholder="Email..." /><br/>
<input type="text" ng-model="user.Address.addr1" placeholder="Addr. Line 1..." />
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Thanks for taking the time to look at this. I'm still learning the caveats of Angular and I didn't know you could user '||' in that way. I ended up using: `` I agree about placeholders, but within my specific context it was useful. – user1791914 Feb 14 '15 at 16:36