I'm editing an existing code that has a lot of angular js expressions which are being detected as unsafe by our automated testing system. I was able to see the article below that describes my case, but I was not able to get any specific way to solve it (I'm mostly seeing $watch and $apply). I guess what I need to know here is where do I make changes on the code?
Related links:
http://blog.angularjs.org/2016/09/angular-16-expression-sandbox-removal.html
https://docs.angularjs.org/guide/security#angularjs-templates-and-expressions
Sample snippets on my code:
Your code looks perfectly fine. I think what you're missing is the "passing user provided content" portion of that warning.
In the first example the only thing you are passing to $apply is a function that YOU have defined, same as the second example. In the last example you don't pass anything to $apply.
The reason they have these warnings is because $apply can be passed a string to evaluate an expression on $scope.
In the same way that
{{$scope.hello = 'Hello, World'}}
will set the hello property of $scope
$scope.$apply('hello = "Hello, World"')
Will do exactly the same. now imagine you pass user defined content to this
$scope.$apply(userPassedString)
Now you have given a user the ability to run arbitrary javascript expressions in your apply function.
To see exactly what I mean by this (and how this is exploitable), I have created a codepen demo for you here: https://codepen.io/codymikol/pen/bGbzbvp
(You'll have to scroll down in the HTML to see the script, I was lazy and din't link it as a separate JS file \_('__')_/
Also if you REALLY want to understand how the above snippet is able to function (and where I learned about getting the function constructor in such a way) you should watch this video by liveoverflow: https://www.youtube.com/watch?v=DkL3jaI1cj0
This was made back when the AngularJS team was trying to create a sandbox around scope expressions to prevent XSS. There are a bunch of videos detailing different exploits people used to get around the sandbox. Because of how complicated creating a sandbox is and how often it was being exploited they decided to remove it entirely and just warn developers about passing user content in such a way.
Related
What is the use of .scope() in AngularJS? I have seen some code examples using this but I am not quite sure what the use is, and I have been unable to find an answer in SO posts and in AngularJS documentation. For example:
var scope = angular.element(document.getElementById("MainWrap")).scope();
Is this somehow similar to use of $digest or $apply?
Here an example of what I use it for every day:
Open Console in dev tools.
Right-click an element in your page that is managed by AngularJS, select inspect element option
Now write in console: angular.element($0).scope()
You just got a scope of said element as that element sees it. You can go up through the parent, manage its content (don't forget to $apply() afterward to test the change, otherwise, it won't bind) or do similar things you can in console with any JS object.
There are more uses for it for sure internally, but this one I find really helpful when debugging. So in relation to $apply() it is and is not linked to it, depending what you use it for.
im looking to implement a directive to display status messages in my ionic angular app.. the idea is that i define a bunch of standard status messages in my template as follows and it's inspired by the stock ng-switch directive..
<status-bar code="statusCode" onShow="onStatusShow" onHide="onStatusHide">
<status-message when-code="OK" style="calm" timeout="3000">My HTML message</status-message>
...
...
<status-message when-complex style-field="style" text-field="text" timeout-field="timeout" />
</status-bar>
my requirements are these:
status-bar
the directive should bind to $scope.statusCode and depending upon its string value, it should activate one of the sub-directives except the when-complex one..
however, if i assign an object to $scope.statusCode, it should activate the when-complex directive if defined..
the directive also exposes an onShow and onHide callbacks..
when changing the value of $scope.statusCode, the previously active sub-directive should be completely hidden before showing the newly active one.. (animations)
status-message
style and timeout attributes are optional and will default to 'stable' and null respectively..
the timeout attribute will cause this sub-directive to show for a short time before clearing $scope.statusCode..
whereas i can write very simple directives, this one is proving to be a bit beyond me.. ive seen the source of ng-switch and its confusing.. i have tried myself as well but i havent gotten really far with this no matter how much ive tried.. im not posting my code approaches here not for the lack of trying but for the sake of cluttering and relevance..
so i was wondering if maybe someone could come up with a possible basic approach on codepen or plunkr that i can use as a base for expanding upon (since this is just a simplified explanation of what i intend to do with this directive).. or atleast point in the directions i need to go in..
after a night of brain-storming and coding punctuated by coffee and smoke breaks.. ive managed to make it work.. once again keeping ng-switch as a base.. the code is a bit long.. and i changed a few requirements along the way for better usability.. and some requirements like #2 and #3 dont work yet.. but im pretty sure ill make it work as well..
so if anybody is having a similar issue or is interested in my solution.. i can post it here.. :)
I upgraded my App to AngularJS 1.2 and so also switched to ui-sortable v 1.2.
The sorting is implemented for Accordion-Groups (from ui-bootstrap). With the master-tree version of sortable i could listen to ng-mouseover/ng-mouseleave inside the accordion headers but with the 1.2 version, the mouseevents are only listening as long as i haven't done any sorting. After performing any change to the sortorder, the mouseevents become deaf...
Here's a Plunker: http://plnkr.co/edit/n8yms9pb7uJp77zZ9LFK?p=preview
Can anybody give me some advice how to fix that?
Thank you
Identity Problem.
elementInsertedByDropping !== elementSelectedAndDragged
In the console, one can verify the assertion above. So that narrows down the category of problem to a relatively familiar one.
I'm learning Angular myself, and I'm also having trouble with ui-sortable; please don't regard my opinions as definitive. However, I believe that the problem is that the $watch listeners need to be re-bound to the new element, as it is being created asynchronously outside of Angular.
The "ng.$rootScope.Scope" documentation describes this situation somewhat clearly in the $apply section. If I am correct, you would need to either $scope.$apply(...) code in your controller, or [preferably] write a custom directive that handles the insertion.
Fortunately, it seems that jQuery-ui-sortable's "update" event can be easily used in a custom directive to ensure that the element is bound. I found that bloggers respectTheCode and Michal Ostruszka discuss the problem of writing jQuery-ui-sortable directives in fairly clear terms; so does a fellow named Greg Gigon and several others, but I'm only allowed to offer you two links at this point.
If I can provide more precise information at a later point, I will revise this answer; I'm still learning this stuff myself, and I would like to know how to do something quite similar.
[edit: I'm not familiar enough with Angular-UI-Sortable to know whether this is a bug or simply missing functionality.]
Looks like a bug in ui-sortable.
My guess: It seems to be losing the bindings from the event directives, probably because it's destroying the old DOM elements and creating a new ones without re-attaching the scope with $compile. I'd save this plunk and submit and issue on their GitHub repository
I've just wasted half an hour hunting for what turned out to be...
<select.... data-ng-options="x as x.name for x in customerController_clipped.options"
instead of
<select.... data-ng-options="x as x.name for x in customerController_Clipped.options"
That is, a one-character typo - in this case, a 'clip...' instead 'Clip...'
Sure, it's easy to see it when it's isolated above - but think of this inside huge HTML content, and you now know why I ask:
Is there a way to ask AngularJS to report any failures in names of bindings, to ease our debugging? A simple console logging of this kind of failure would suffice, instead of a silent operation that leaves our components empty...
I can't see anything built in for doing this, though maybe you could raise with angular.js as a feature request, or try writing a pull request for putting an option in $parseProvider? If you want to do this the only way I can see right now is by altering the code in the $parse service which does the interpreting of any expressions.
I've plunked a quick test to see how easy it is. The original code is from angular 1.1.5. Search for ANDYMOD in the angular-1.1.5.js file to see the code I've edited. This basically adds a console.log for whenever the y and z parts of a 'x.y.z' expression are undefined or null, rather than ignoring it.
This is in no way a production-worthy solution, and doesn't work it you want to use ng-csp, but it shows something can be done at least. Maybe you can sub these few lines in if you ever need to test again...
I have an issue with angularjs and the email input type.
I want to create dynamic inputs with a directive, but the input type validation might be buggy.
Here is the jsfiddle of my test
http://jsfiddle.net/NPCHr
To avoid some trouble I have to use this trick
element.find('input')[0].type = input.type;
When I had a second character in the input the model field disappears (In the html panel)
I don't know why is this a bug or am I doing something wrong ?
The problem with your directive is not that e-mail validation doesn't work but the fact that dynamic type attribute is not supported by AngularJS (and jQuery BTW). This is due to the fact that IE doesn't allow changing input's type on-the-fly (Changing the <input> type in IE with JavaScript).
This topic was discussed in great details on the AngularJS mailing list, here is the reference: https://groups.google.com/forum/#!topic/angular/Itl-fYzeF18 where someone had exactly the same problem as yours.
The way out of this situation is to manually compile a template using the $compile service. Unfortunately this is not trivial, you can see evidence of some experiments here: https://github.com/angular-ui/angular-ui/pull/191
An alternative, simpler approach is to use ngInclude directive to include different inputs based on their type. Yet another possibility is to use the compile function and manually transform template's markup. But yes, all of those techniques require several lines of non-trivial code.