AngularJS

“Angular” Sanitize

We don’t actually need $sanitize to sanitize strings.

ng-bind automatically implements sanitizing in the background with textContent. However, sometimes we need to pass string in as template in controllers and services, or pass it in as the exact content of “name” attribute of an input, then $sanitize doesn’t work anymore.

What $sanitize does is that it renders the content as safe html to render with innerHTML, but what it does not do is sanitizing only attributes of elements. Sanitizing HTML and sanitizing textContent/attributes are entirely different things.

See the comparisons here. The string to be sanitized is: "><img src='https://tinyurl.com/ycosred9' onload=prompt('XSS')>.

0

From the 3 examples above, we can see that if we try to use $sanitize(msg) in the controller to sanitize textContent or attribute, what comes out will no longer be the same string any more. For one thing, if we try to use {{ $sanitize(msg) }} in html, all the &#34;&gt; still remain. For another, the “onload” part of the string is gone.

Sanitizing doesn’t need to be so complicated.

It doesn’t even need to involve Angular at all.

Solution

const str = `><img src='https://tinyurl.com/ycosred9' onload=prompt('XSS')>`;
const ele = document.createElement("div");

// use setAttribute to set attributes
ele.setAttribute("name", str);

// use textContent to set the content of the element
ele.textContent = str;

By creating an element in JavaScript and using built-in APIs to set attribute and element content, we can utilize browsers’ own sanitize function.

Then, to make use of the element we created:

// 1. Append it to the element we want
document.body.appendChild(ele);

// 2. Or if we need the string version of the element, use outerHTML to get it
const templateString = ele.outerHTML;

Read more about dealing with Cross-Site Scripting here.

Standard