Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

XSS issues with server-rendered Angular templates #5601

Closed
@triskweline

Description

@triskweline

Dear Angular community,

we would greatly appreciate any comments on the issue below.

Overview of the issue:

When rendering Angular templates with a server-side templating engine like ERB or Haml it is easy to introduce XSS vulnerabilities. These vulnerabilities are enabled by AngularJS evaluating user-provided strings containing interpolation symbols (default symbols are {{ and }}).

The standard mitigation strategy by templating engines is to always escape meaningful symbols in strings (unless they are explicitely marked as "safe"). Unfortunately the inability to escape AngularJS interpolation symbols makes it hard to apply this strategy here.

Reproducing the issue:

We are using AngularJS for the frontend and Rails in the backend. While we have written full Single Page Applications with AngularJS, we are often embedding small snippets of AngularJS in server-rendered views. We love that AngularJS lets us replace jQuery spaghetti with simple code like this:

<div ng-show="detailsShown">
  <%= user.profile %>
</div>

<span ng-click="detailsShown = true">Show details</span>

The problem is that the code snippet above enables Cross Site Scripting (XSS). If the server-parsed expression user.profile contains AngularJS markup like "Foo {{signOut()}} Bar", it will trigger functions on the current scope, allowing an attacker to trigger side effects on another computer.

Proposed fix:

The standard mitigation strategy by templating engines is to always escape symbols that have meaning for downsteam parsers, unless they are explicitely marked as "safe". E. g. if the server-parsed expression user.profile in the code example above would yield the string "Foo <script>alert('owned')</script> Bar", Rails, Haml, etc. would automatically replace the angle brackets with HTML entities.

To allow HTML tags to be rendered without escaping, the developer needs to explicitely mark a string as "safe" like so:

<%= user.profile.html_safe %>

(AngularJS actually uses this approach itself, when inserting the results of an evaluated Angular expression into the DOM.)

A good default for people rendering Angular templates using server-side templating engines would be to make templating engines automatically escape Angular interpolation symbols unless an evaluated string is explictely flagged as "safe". A patch for engines like ERB or Haml would be easily created, but unfortunately Angular's $interpolate service does not recognize any kind of escape symbol.

We propose that the $interpolate service should recognize escaped interpolation symbols like this:

Foo \{\{signOut()\}\} Bar

... or maybe a second pair of start/end symbols.

When encountering escaped interpolation symbols, the service would not evaluate the enclosed expression. Instead it would strip the escape symbols from the string.

(Note that we first tried to replace the curly braces with their HTML entities, which would have the added bonus of being output-neutral outside of an ng-app element. However, entitized braces are still recognized and their contents evaluated by Angular. We're not sure if the entities are expanded by Angular or by the browser.)

Plea to not dismiss this issue

We understand that this issue is not an actual bug in AngularJS, but (like all XSS issues) is caused by combining multiple technologies that are unaware of each other. Still we believe that AngularJS' ability to co-exist with non-Angular code in the same DOM is one of AngularJS greatest strengths. It sets Angular apart from frameworks like Ember, which need to own the entire page.

By offering a way to escape interpolation symbols (or maybe some other solution we didn't think of), AngularJS could be used safely in combination with upstream templating engines.

What do you think?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions