Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 705d8c5

Browse files
chalinnaomiblack
authored andcommitted
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: angular/angular#8511
1 parent 909f230 commit 705d8c5

File tree

7 files changed

+58
-35
lines changed

7 files changed

+58
-35
lines changed
+15-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/// <reference path="../_protractor/e2e.d.ts" />
22
'use strict';
3+
34
describe('Security E2E Tests', () => {
4-
beforeAll(function() { browser.get(''); });
5+
beforeAll(() => browser.get(''));
56

67
it('sanitizes innerHTML', () => {
78
let interpolated = element(By.className('e2e-inner-html-interpolated'));
@@ -13,13 +14,23 @@ describe('Security E2E Tests', () => {
1314
expect(bold.getText()).toContain('Syntax');
1415
});
1516

17+
it('escapes untrusted URLs', () => {
18+
let untrustedUrl = element(By.className('e2e-dangerous-url'));
19+
expect(untrustedUrl.getAttribute('href')).toMatch(/^unsafe:javascript/);
20+
});
21+
1622
it('binds trusted URLs', () => {
17-
let dangerousUrl = element(By.className('e2e-dangerous-url'));
18-
expect(dangerousUrl.getAttribute('href')).toMatch(/^javascript:alert/);
23+
let trustedUrl = element(By.className('e2e-trusted-url'));
24+
expect(trustedUrl.getAttribute('href')).toMatch(/^javascript:alert/);
25+
});
26+
27+
it('escapes untrusted resource URLs', () => {
28+
let iframe = element(By.className('e2e-iframe-untrusted-src'));
29+
expect(iframe.getAttribute('src')).toBe('');
1930
});
2031

2132
it('binds trusted resource URLs', () => {
22-
let iframe = element(By.className('e2e-iframe'));
33+
let iframe = element(By.className('e2e-iframe-trusted-src'));
2334
expect(iframe.getAttribute('src')).toMatch(/^https:\/\/www.youtube.com\//);
2435
});
2536
});

public/docs/_examples/security/ts/app/app.component.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { BypassSecurityComponent } from './bypass-security.component';
55
import { InnerHtmlBindingComponent } from './inner-html-binding.component';
66

77
@Component({
8-
selector: 'app-root',
8+
selector: 'my-app',
99
template: `
1010
<h1>Security</h1>
1111
<inner-html-binding></inner-html-binding>
@@ -14,7 +14,7 @@ import { InnerHtmlBindingComponent } from './inner-html-binding.component';
1414
directives: [
1515
BypassSecurityComponent,
1616
InnerHtmlBindingComponent,
17-
],
17+
]
1818
})
1919
export class AppComponent {
2020
}

public/docs/_examples/security/ts/app/bypass-security.component.html

+8-3
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
<h3>Bypass Security Component</h3>
33

44
<!--#docregion dangerous-url -->
5-
<h4>A dangerous URL:</h4>
6-
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me.</a></p>
5+
<h4>A untrusted URL:</h4>
6+
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
7+
<h4>A trusted URL:</h4>
8+
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
79
<!--#enddocregion dangerous-url -->
810

911
<!--#docregion iframe-videoid -->
1012
<h4>Resource URL:</h4>
1113
<p><label>Showing: <input (input)="updateVideoUrl($event.target.value)"></label></p>
12-
<iframe class="e2e-iframe" width="640" height="390" [src]="videoUrl"></iframe>
14+
<p>Trusted:</p>
15+
<iframe class="e2e-iframe-trusted-src" width="640" height="390" [src]="videoUrl"></iframe>
16+
<p>Untrusted:</p>
17+
<iframe class="e2e-iframe-untrusted-src" width="640" height="390" [src]="dangerousVideoUrl"></iframe>
1318
<!--#enddocregion iframe-videoid -->
1419

1520
<!--#enddocregion -->

public/docs/_examples/security/ts/app/bypass-security.component.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,31 @@ import { DomSanitizationService, SafeResourceUrl, SafeUrl } from '@angular/platf
88
templateUrl: 'app/bypass-security.component.html',
99
})
1010
export class BypassSecurityComponent {
11-
dangerousUrl: SafeUrl;
11+
dangerousUrl: string;
12+
trustedUrl: SafeUrl;
13+
dangerousVideoUrl: string;
1214
videoUrl: SafeResourceUrl;
1315

1416
// #docregion trust-url
1517
constructor(private sanitizer: DomSanitizationService) {
16-
// javascript: URLs are dangerous if attacker controlled. Angular sanitizes them in data
17-
// binding, but we can explicitly tell Angular to trust this value:
18-
this.dangerousUrl = sanitizer.bypassSecurityTrustUrl('javascript:alert("Hi there")');
18+
// javascript: URLs are dangerous if attacker controlled.
19+
// Angular sanitizes them in data binding, but we can
20+
// explicitly tell Angular to trust this value:
21+
this.dangerousUrl = 'javascript:alert("Hi there")';
22+
this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
1923
// #enddocregion trust-url
2024
this.updateVideoUrl('PUBnlbjZFAI');
2125
}
2226

2327
// #docregion trust-video-url
2428
updateVideoUrl(id: string) {
2529
// Appending an ID to a YouTube URL is safe.
26-
// Always make sure to construct SafeValue objects as close as possible to the input data, so
30+
// Always make sure to construct SafeValue objects as
31+
// close as possible to the input data, so
2732
// that it's easier to check if the value is safe.
33+
this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
2834
this.videoUrl =
29-
this.sanitizer.bypassSecurityTrustResourceUrl('https://www.youtube.com/embed/' + id);
35+
this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
3036
}
3137
// #enddocregion trust-video-url
3238
}
33-
// #enddocregion

public/docs/_examples/security/ts/app/inner-html-binding.component.ts

-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,3 @@ export class InnerHtmlBindingComponent {
1111
// E.g. a user/attacker controlled value from a URL.
1212
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
1313
}
14-
// #enddocregion inner-html-controller

public/docs/_examples/security/ts/index.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
<!DOCTYPE html>
21
<!-- #docregion -->
2+
<!DOCTYPE html>
33
<html>
44
<head>
55
<title>Angular Content Security</title>
@@ -21,6 +21,6 @@
2121
</head>
2222

2323
<body>
24-
<app-root>Loading...</app-root>
24+
<my-app>Loading...</my-app>
2525
</body>
2626
</html>

public/docs/ts/latest/guide/security.jade

+19-16
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
block includes
22
include ../_util-fns
33
:marked
4-
Web application security has many aspects. This documentation describes Angular's built in
4+
Web application security has many aspects. This chapter describes Angular's built in
55
protections against common web application vulnerabilities and attacks, such as Cross Site
66
Scripting Attacks. It does not cover application level security, such as authentication (_Who is
77
this user?_) or authorization (_What can this user do?_).
@@ -50,7 +50,7 @@ h2#best-practices Best Practices
5050
h2#xss Preventing Cross-Site Scripting (XSS)
5151
:marked
5252
[Cross-Site Scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) enables attackers
53-
to inject malicious code into web pages. Such code can then for example steal user's data (in
53+
to inject malicious code into web pages. Such code can then, for example, steal user's data (in
5454
particular their login data), or perform actions impersonating the user. This is one of the most
5555
common attacks on the web.
5656

@@ -81,10 +81,10 @@ h2#xss Preventing Cross-Site Scripting (XSS)
8181

8282
Angular defines four security contexts: HTML, style, URL, and resource URL.
8383

84-
* HTML is used when interpreting a value as HTML, e.g. when binding to `innerHtml`
84+
* HTML is used when interpreting a value as HTML, e.g., when binding to `innerHtml`
8585
* Style is used when binding CSS into the `style` property
8686
* URL is used for URL properties such as `<a href>`
87-
* Resource URLs are URLs that will be loaded and executed as code, e.g. in `<script src>`
87+
* Resource URLs are URLs that will be loaded and executed as code, e.g., in `<script src>`
8888

8989
Angular sanitizes untrusted values for the first three items; sanitizing resource URLs is not
9090
possible as they contain arbitrary code. In development mode, Angular prints a console warning
@@ -95,7 +95,8 @@ h2#xss Preventing Cross-Site Scripting (XSS)
9595
The template below binds the value of `htmlSnippet`, once by interpolating it into an element's
9696
content, and once by binding it to the `innerHTML` property of an element.
9797

98-
+makeExample('security/ts/app/inner-html-binding.component.html')(format=".")
98+
+makeExcerpt('app/inner-html-binding.component.html')
99+
99100
:marked
100101
Interpolated content is always escaped - the HTML is not interpreted, and the browser displays
101102
angle brackets in the elements text content.
@@ -121,8 +122,7 @@ figure.image-display
121122

122123
### Content Security Policy
123124

124-
A [Content Security Policy (CSP)]
125-
(http://www.html5rocks.com/en/tutorials/security/content-security-policy/) is a defense-in-depth
125+
A [Content Security Policy (CSP)](http://www.html5rocks.com/en/tutorials/security/content-security-policy/) is a defense-in-depth
126126
technique to prevent XSS. To enable CSP, configure your web server to return an appropriate
127127
`Content-Security-Policy` HTTP header.
128128

@@ -139,7 +139,7 @@ figure.image-display
139139
### Server side XSS protection
140140

141141
HTML constructed on the server is vulnerable to injection attacks. Injecting template code into an
142-
Angular application is the same as injecting executable code (e.g. JavaScript) into the
142+
Angular application is the same as injecting executable code (e.g., JavaScript) into the
143143
application; it gives the attacker full control over the application. To prevent this, make sure
144144
to use a templating language that automatically escapes values to prevent XSS vulnerabilities on
145145
the server. Do not generate Angular templates on the server side using a templating language, this
@@ -181,7 +181,7 @@ figure.image-display
181181
If we need to convert user input into a trusted value, it can be convenient to do so in a
182182
controller method. The template below allows users to enter a YouTube video ID, and load the
183183
corresponding video in an `<iframe>`. The `<iframe src>` attribute is a resource URL security
184-
context, because an untrusted source can e.g. smuggle in file downloads that unsuspecting users
184+
context, because an untrusted source can, e.g., smuggle in file downloads that unsuspecting users
185185
would execute. So we call a method on the controller to construct a trusted video URL, which
186186
Angular then allows binding into `<iframe src>`.
187187

@@ -198,12 +198,12 @@ h2#http HTTP-level Vulnerabilities
198198
h3#xsrf Cross-site Request Forgery (XSRF)
199199
:marked
200200
In a Cross-site Request Forgery (XSRF or CSRF), an attacker tricks the user into visiting a
201-
_different_ page, and has them e.g. submit a form that sends a request to your application's
201+
_different_ page, and has them, e.g., submit a form that sends a request to your application's
202202
web server. If the user is logged into your application, the browser will send authentication
203-
cookies, and the attacker could - for example - cause a bank transfer in the user's name with
203+
cookies, and the attacker could &mdash; for example &mdash; cause a bank transfer in the user's name with
204204
the right request.
205205

206-
To prevent this, your application must make sure that user requests originate in your own
206+
To prevent this, your application must ensure that user requests originate in your own
207207
application, not on a different site. A common technique is that the server sends a randomly
208208
generated authentication token in a cookie, often with the name `XSRF-TOKEN`. Cookies can only
209209
be read by the website on which they are set, so only your own application can read this token. On
@@ -220,14 +220,17 @@ h3#xsrf Cross-site Request Forgery (XSRF)
220220

221221
Angular applications can customize cookie and header names by binding their own
222222
`CookieXSRFStrategy` value, or implement an entirely custom `XSRFStrategy` by providing a custom
223-
binding for that type, by adding
224-
`provide(XSRFStrategy, {useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name')})` or
225-
`provide(XSRFStrategy, {useClass: MyXSRFStrategy})` to your providers list.
223+
binding for that type, by adding either of the following to your providers list:
224+
225+
code-example(language="typescript").
226+
{ provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name')}
227+
{ provide: XSRFStrategy, useClass: MyXSRFStrategy}
226228

229+
:marked
227230
Learn about Cross Site Request Forgery (XSRF) at the Open Web Application Security Project (OWASP)
228231
[here](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29) and
229232
[here](https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet). This [Stanford University
230-
paper](https://seclab.stanford.edu/websec/csrf/csrf.pdf) is a rich source of detail.
233+
paper](https://seclab.stanford.edu/websec/csrf/csrf.pdf) is also a rich source of detail.
231234

232235
h3#xssi Cross-site Script Inclusion (XSSI)
233236
:marked

0 commit comments

Comments
 (0)