Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Typeahead vulnerable to cross-site scripting attack #3175

Closed
unitymarc opened this issue Jan 9, 2015 · 5 comments
Closed

Typeahead vulnerable to cross-site scripting attack #3175

unitymarc opened this issue Jan 9, 2015 · 5 comments

Comments

@unitymarc
Copy link

Consider the following data set returned from a server:

['Alabama', 'Alaska', '<script>alert("gotcha!")</script>', 'Arkansas']

By default, the typeahead component uses bind-html-unsafe to render the follow result:

<a tabindex="-1" bind-html-unsafe="match.label | typeaheadHighlight:query" class="ng-scope ng-binding"><script>alert('gotcha!')</script></a>

Note the use of the (non-standard?) bind-html-unsafe (i.e., neither ng-bind-html nor ng-bind-html-unsafe). The result is that any typeahead linked to an uncontrolled data source (say, for example, a Google search) is vulnerable to arbitrary data execution on the client...this script isn't just rendered as text, it executes the alert. This seems to be a very powerful vector for an XSS attack.

Our current workaround is to use a custom template:

//Add custom template
<input class="typeahead-control"
           type="text" 
           ng-model="step.data"
           typeahead="item for item in theDataSet"
           typeahead-template-url="safeLookaheadTemplate.html" />

//Custom template (uses ng-bind-html)
<a ng-bind-html="match.label | sanitizeHtmlFilter | typeaheadHighlight:query">
</a>

//Filter to pass the input through $sanitize. This ensures that the typeaheadHighlight filter
//doesn't parse the illegal <script> tag, thereby raising badparse errors in the sanitizer.
var module = angular.module('sanitizeHtmlFilter', ['ngSanitize']);
module.filter('sanitizeHtmlFilter', ['$filter', '$sanitize', function($filter, $sanitize) {
    return function(input) {
        return $sanitize(input);
    }
}]);

Thanks for all your hard work.

@unitymarc
Copy link
Author

UPDATE: Further work on this suggests that this may not be a bug on your side. We have a custom directive that allows the user to click a pulldown carat to trigger the typeahead and see the whole list of available options. It appears that the field is only vulnerable to this form of attack if the typeahead is empty, as in our case. In normal use this can never happen, so while the issue isn't entirely moot, the danger is largely mitigated.

I'll update (and probably close) this issue once I'm more certain.

@unitymarc
Copy link
Author

I'm reasonably satisfied that in normal use this won't be an issue, so I'm closing. Apologies for the error.

@karianna
Copy link
Contributor

Thanks for getting back to us!

@RyanBard
Copy link

This is still an issue and seems like it should be a concern. Should this issue be re-opened?

http://plnkr.co/edit/STR8SfgvtUdNopDS5Lam?p=preview

@RyanBard
Copy link

New issue created: #4181

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants