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?

4
  • You can surely use user.Address.addr1? How are you suing it? Commented Feb 14, 2015 at 15:58
  • 1
    This question, especially with the answer, edits, and comments, smells of the XY problem. meta.stackexchange.com/questions/66377/what-is-the-xy-problem/…. 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. Commented Feb 14, 2015 at 16:00
  • The bracket notation will still work, but you need to add some additional logic. Something like in this answer to the question Multiple level attribute retrieval using array notation from a JSON object Commented Feb 14, 2015 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. Commented Feb 14, 2015 at 16:16

2 Answers 2

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..." />
Sign up to request clarification or add additional context in comments.

1 Comment

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: <input type="text" ng-model="user.Address.addr1" placeholder="{{ master.user.Address.addr1 || 'Addr. Line 1...' }}" /> I agree about placeholders, but within my specific context it was useful.
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?

2 Comments

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": docs.angularjs.org/api/ng/type/$rootScope.Scope#$eval
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.

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.