Why does AngularJS strip out data- attributes when

2019-06-19 11:14发布

问题:

I am using a contentEditable div to enable users to format their articles. I do some processing on the html content and persist it.

I am using ng-bind-html to render the result when viewers want to read the article. I don't want to use $sce.trustAsHtml because I still want AngularJS to sanitize the user input and because I don't trust all the input. All I want is for AngularJS sanitization to allow some attributes on elements. It seems to strip ID, and data- attributes. (but keeps class and title) .

Is data- attributes considered harmful? How can an attacker may use them to attack the end user? And is there a way to use them safely and let Angular not strip them out?

Here's an example:

article.body = '<p data-guid="afasfa-afasfafas-faf-asasf" class="guid-tagged">Yes this is my article</p>';
<article ng-bind-html='article.body'></article>

Here's what Angular outputs inside the article tag (notice the stripped out data- attribute):

<p class="guid-tagged">Yes this is my article</p>

Thanks

回答1:

As mentioned in the comment, ng-bind-html passes the data through a sanitizer. This sanitizer removes a number of attributes from all input passed in it. This issue may help explain more: ngSanitize issue concerning whitelisting attributes. This part of the source code includes all the attributes considered valid and therefore left untouched by ngSanitize.



回答2:

While the Angular and ngSanitize crew sort this out, I found this thread helpful to create a workaround. In particular, the answer speaking to a dynamically defined Property.

Binding to is-open with such a property, I was able to attach click handlers on anchor tags after ngSanitize had finished sanitizing.

Here's the HTML after being sanitized, note that I'm using cite to store the target anchor id as it is one of the attributes that ngSanitize ignores. (You could try using the href but I wanted to leave that alone):

Please see <a href='#' cite='#another_faq'>here</a>

The code in the setter for the Property (see the referenced SO above) then manipulates DOM events which I believe is counter to the Angular methodology but sometimes you have to stop banging your head and get it to work:

if (isOpened) $('p.faq.answer').eq(item.position).find('a[cite]').each -> $(this).bind 'click', () -> $($(this).attr('cite')).click()

And then make sure you have the proper anchor with target id of #another_faq, in this case.