From 705d8c50fd012192677fd6fcf01d9b4623b3e488 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Thu, 30 Jun 2016 07:21:55 -0700 Subject: [PATCH] docs(security): proofread prose, app now shows good and bad - App now shows how Angular handles untrusted URLs and resources - E2e test covered new functionality - Copyedits to prose - Updated provider expressions to use latest syntax The original security feature tracker: https://github.com/angular/angular/issues/8511 --- public/docs/_examples/security/e2e-spec.ts | 19 +++++++--- .../security/ts/app/app.component.ts | 4 +-- .../ts/app/bypass-security.component.html | 11 ++++-- .../ts/app/bypass-security.component.ts | 19 ++++++---- .../ts/app/inner-html-binding.component.ts | 1 - public/docs/_examples/security/ts/index.html | 4 +-- public/docs/ts/latest/guide/security.jade | 35 ++++++++++--------- 7 files changed, 58 insertions(+), 35 deletions(-) diff --git a/public/docs/_examples/security/e2e-spec.ts b/public/docs/_examples/security/e2e-spec.ts index 410f1428e1..d1a373a781 100644 --- a/public/docs/_examples/security/e2e-spec.ts +++ b/public/docs/_examples/security/e2e-spec.ts @@ -1,7 +1,8 @@ /// 'use strict'; + describe('Security E2E Tests', () => { - beforeAll(function() { browser.get(''); }); + beforeAll(() => browser.get('')); it('sanitizes innerHTML', () => { let interpolated = element(By.className('e2e-inner-html-interpolated')); @@ -13,13 +14,23 @@ describe('Security E2E Tests', () => { expect(bold.getText()).toContain('Syntax'); }); + it('escapes untrusted URLs', () => { + let untrustedUrl = element(By.className('e2e-dangerous-url')); + expect(untrustedUrl.getAttribute('href')).toMatch(/^unsafe:javascript/); + }); + it('binds trusted URLs', () => { - let dangerousUrl = element(By.className('e2e-dangerous-url')); - expect(dangerousUrl.getAttribute('href')).toMatch(/^javascript:alert/); + let trustedUrl = element(By.className('e2e-trusted-url')); + expect(trustedUrl.getAttribute('href')).toMatch(/^javascript:alert/); + }); + + it('escapes untrusted resource URLs', () => { + let iframe = element(By.className('e2e-iframe-untrusted-src')); + expect(iframe.getAttribute('src')).toBe(''); }); it('binds trusted resource URLs', () => { - let iframe = element(By.className('e2e-iframe')); + let iframe = element(By.className('e2e-iframe-trusted-src')); expect(iframe.getAttribute('src')).toMatch(/^https:\/\/www.youtube.com\//); }); }); diff --git a/public/docs/_examples/security/ts/app/app.component.ts b/public/docs/_examples/security/ts/app/app.component.ts index 153e6b9e49..a2fc7e7320 100644 --- a/public/docs/_examples/security/ts/app/app.component.ts +++ b/public/docs/_examples/security/ts/app/app.component.ts @@ -5,7 +5,7 @@ import { BypassSecurityComponent } from './bypass-security.component'; import { InnerHtmlBindingComponent } from './inner-html-binding.component'; @Component({ - selector: 'app-root', + selector: 'my-app', template: `

Security

@@ -14,7 +14,7 @@ import { InnerHtmlBindingComponent } from './inner-html-binding.component'; directives: [ BypassSecurityComponent, InnerHtmlBindingComponent, - ], + ] }) export class AppComponent { } diff --git a/public/docs/_examples/security/ts/app/bypass-security.component.html b/public/docs/_examples/security/ts/app/bypass-security.component.html index 75b7734dd4..1b0a9d0c0e 100644 --- a/public/docs/_examples/security/ts/app/bypass-security.component.html +++ b/public/docs/_examples/security/ts/app/bypass-security.component.html @@ -2,14 +2,19 @@

Bypass Security Component

-

A dangerous URL:

-

Click me.

+

A untrusted URL:

+

Click me

+

A trusted URL:

+

Click me

Resource URL:

- +

Trusted:

+ +

Untrusted:

+ diff --git a/public/docs/_examples/security/ts/app/bypass-security.component.ts b/public/docs/_examples/security/ts/app/bypass-security.component.ts index 6a5f350d28..a18d4251a5 100644 --- a/public/docs/_examples/security/ts/app/bypass-security.component.ts +++ b/public/docs/_examples/security/ts/app/bypass-security.component.ts @@ -8,14 +8,18 @@ import { DomSanitizationService, SafeResourceUrl, SafeUrl } from '@angular/platf templateUrl: 'app/bypass-security.component.html', }) export class BypassSecurityComponent { - dangerousUrl: SafeUrl; + dangerousUrl: string; + trustedUrl: SafeUrl; + dangerousVideoUrl: string; videoUrl: SafeResourceUrl; // #docregion trust-url constructor(private sanitizer: DomSanitizationService) { - // javascript: URLs are dangerous if attacker controlled. Angular sanitizes them in data - // binding, but we can explicitly tell Angular to trust this value: - this.dangerousUrl = sanitizer.bypassSecurityTrustUrl('javascript:alert("Hi there")'); + // javascript: URLs are dangerous if attacker controlled. + // Angular sanitizes them in data binding, but we can + // explicitly tell Angular to trust this value: + this.dangerousUrl = 'javascript:alert("Hi there")'; + this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl); // #enddocregion trust-url this.updateVideoUrl('PUBnlbjZFAI'); } @@ -23,11 +27,12 @@ export class BypassSecurityComponent { // #docregion trust-video-url updateVideoUrl(id: string) { // Appending an ID to a YouTube URL is safe. - // Always make sure to construct SafeValue objects as close as possible to the input data, so + // Always make sure to construct SafeValue objects as + // close as possible to the input data, so // that it's easier to check if the value is safe. + this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id; this.videoUrl = - this.sanitizer.bypassSecurityTrustResourceUrl('https://www.youtube.com/embed/' + id); + this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl); } // #enddocregion trust-video-url } -// #enddocregion diff --git a/public/docs/_examples/security/ts/app/inner-html-binding.component.ts b/public/docs/_examples/security/ts/app/inner-html-binding.component.ts index 95a9f55979..0419e5b324 100644 --- a/public/docs/_examples/security/ts/app/inner-html-binding.component.ts +++ b/public/docs/_examples/security/ts/app/inner-html-binding.component.ts @@ -11,4 +11,3 @@ export class InnerHtmlBindingComponent { // E.g. a user/attacker controlled value from a URL. htmlSnippet = 'Template Syntax'; } -// #enddocregion inner-html-controller diff --git a/public/docs/_examples/security/ts/index.html b/public/docs/_examples/security/ts/index.html index b665a8bc6f..16eeeb2b2a 100644 --- a/public/docs/_examples/security/ts/index.html +++ b/public/docs/_examples/security/ts/index.html @@ -1,5 +1,5 @@ - + Angular Content Security @@ -21,6 +21,6 @@ - Loading... + Loading... diff --git a/public/docs/ts/latest/guide/security.jade b/public/docs/ts/latest/guide/security.jade index c83e07238b..701f10d4e6 100644 --- a/public/docs/ts/latest/guide/security.jade +++ b/public/docs/ts/latest/guide/security.jade @@ -1,7 +1,7 @@ block includes include ../_util-fns :marked - Web application security has many aspects. This documentation describes Angular's built in + Web application security has many aspects. This chapter describes Angular's built in protections against common web application vulnerabilities and attacks, such as Cross Site Scripting Attacks. It does not cover application level security, such as authentication (_Who is this user?_) or authorization (_What can this user do?_). @@ -50,7 +50,7 @@ h2#best-practices Best Practices h2#xss Preventing Cross-Site Scripting (XSS) :marked [Cross-Site Scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) enables attackers - to inject malicious code into web pages. Such code can then for example steal user's data (in + to inject malicious code into web pages. Such code can then, for example, steal user's data (in particular their login data), or perform actions impersonating the user. This is one of the most common attacks on the web. @@ -81,10 +81,10 @@ h2#xss Preventing Cross-Site Scripting (XSS) Angular defines four security contexts: HTML, style, URL, and resource URL. - * HTML is used when interpreting a value as HTML, e.g. when binding to `innerHtml` + * HTML is used when interpreting a value as HTML, e.g., when binding to `innerHtml` * Style is used when binding CSS into the `style` property * URL is used for URL properties such as `` - * Resource URLs are URLs that will be loaded and executed as code, e.g. in `