| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  | import {SECURITY_SCHEMA} from '@angular/compiler/src/schema/dom_security_schema'; | 
					
						
							| 
									
										
										
										
											2019-10-14 13:59:17 -07:00
										 |  |  | import {LView} from '@angular/core/src/render3/interfaces/view'; | 
					
						
							|  |  |  | import {enterView, leaveView} from '@angular/core/src/render3/state'; | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-11 10:58:18 -07:00
										 |  |  | import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl} from '../../src/sanitization/bypass'; | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  | import {getUrlSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl} from '../../src/sanitization/sanitization'; | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  | import {SecurityContext} from '../../src/sanitization/security'; | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-28 14:45:31 -08:00
										 |  |  | function fakeLView(): LView { | 
					
						
							| 
									
										
										
										
											2019-02-23 11:14:35 -08:00
										 |  |  |   return [null, {}] as LView; | 
					
						
							| 
									
										
										
										
											2019-01-28 14:45:31 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  | describe('sanitization', () => { | 
					
						
							| 
									
										
										
										
											2019-10-14 13:59:17 -07:00
										 |  |  |   beforeEach(() => enterView(fakeLView(), null)); | 
					
						
							|  |  |  |   afterEach(() => leaveView()); | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |   class Wrap { | 
					
						
							|  |  |  |     constructor(private value: string) {} | 
					
						
							|  |  |  |     toString() { return this.value; } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   it('should sanitize html', () => { | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeHtml('<div></div>')).toEqual('<div></div>'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeHtml(new Wrap('<div></div>'))).toEqual('<div></div>'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeHtml('<img src="javascript:true">')) | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |         .toEqual('<img src="unsafe:javascript:true">'); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeHtml(new Wrap('<img src="javascript:true">'))) | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |         .toEqual('<img src="unsafe:javascript:true">'); | 
					
						
							| 
									
										
										
										
											2019-07-31 13:15:50 -07:00
										 |  |  |     expect(() => ɵɵsanitizeHtml(bypassSanitizationTrustUrl('<img src="javascript:true">'))) | 
					
						
							|  |  |  |         .toThrowError(/Required a safe HTML, got a URL/); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeHtml(bypassSanitizationTrustHtml('<img src="javascript:true">'))) | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |         .toEqual('<img src="javascript:true">'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should sanitize url', () => { | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeUrl('http://server')).toEqual('http://server'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeUrl(new Wrap('http://server'))).toEqual('http://server'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeUrl('javascript:true')).toEqual('unsafe:javascript:true'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeUrl(new Wrap('javascript:true'))).toEqual('unsafe:javascript:true'); | 
					
						
							| 
									
										
										
										
											2019-07-31 13:15:50 -07:00
										 |  |  |     expect(() => ɵɵsanitizeUrl(bypassSanitizationTrustHtml('javascript:true'))) | 
					
						
							|  |  |  |         .toThrowError(/Required a safe URL, got a HTML/); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeUrl(bypassSanitizationTrustUrl('javascript:true'))).toEqual('javascript:true'); | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should sanitize resourceUrl', () => { | 
					
						
							|  |  |  |     const ERROR = 'unsafe value used in a resource URL context (see http://g.co/ng/security#xss)'; | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(() => ɵɵsanitizeResourceUrl('http://server')).toThrowError(ERROR); | 
					
						
							|  |  |  |     expect(() => ɵɵsanitizeResourceUrl('javascript:true')).toThrowError(ERROR); | 
					
						
							|  |  |  |     expect(() => ɵɵsanitizeResourceUrl(bypassSanitizationTrustHtml('javascript:true'))) | 
					
						
							| 
									
										
										
										
											2019-07-31 13:15:50 -07:00
										 |  |  |         .toThrowError(/Required a safe ResourceURL, got a HTML/); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeResourceUrl(bypassSanitizationTrustResourceUrl('javascript:true'))) | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |         .toEqual('javascript:true'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should sanitize style', () => { | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeStyle('red')).toEqual('red'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeStyle(new Wrap('red'))).toEqual('red'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeStyle('url("http://server")')).toEqual('unsafe'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeStyle(new Wrap('url("http://server")'))).toEqual('unsafe'); | 
					
						
							| 
									
										
										
										
											2019-07-31 13:15:50 -07:00
										 |  |  |     expect(() => ɵɵsanitizeStyle(bypassSanitizationTrustHtml('url("http://server")'))) | 
					
						
							|  |  |  |         .toThrowError(/Required a safe Style, got a HTML/); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeStyle(bypassSanitizationTrustStyle('url("http://server")'))) | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |         .toEqual('url("http://server")'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should sanitize script', () => { | 
					
						
							|  |  |  |     const ERROR = 'unsafe value used in a script context'; | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(() => ɵɵsanitizeScript('true')).toThrowError(ERROR); | 
					
						
							|  |  |  |     expect(() => ɵɵsanitizeScript('true')).toThrowError(ERROR); | 
					
						
							| 
									
										
										
										
											2019-07-31 13:15:50 -07:00
										 |  |  |     expect(() => ɵɵsanitizeScript(bypassSanitizationTrustHtml('true'))) | 
					
						
							|  |  |  |         .toThrowError(/Required a safe Script, got a HTML/); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeScript(bypassSanitizationTrustScript('true'))).toEqual('true'); | 
					
						
							| 
									
										
										
										
											2018-03-01 17:14:01 -08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should select correct sanitizer for URL props', () => { | 
					
						
							|  |  |  |     // making sure security schema we have on compiler side is in sync with the `getUrlSanitizer`
 | 
					
						
							|  |  |  |     // runtime function definition
 | 
					
						
							|  |  |  |     const schema = SECURITY_SCHEMA(); | 
					
						
							|  |  |  |     const contextsByProp: Map<string, Set<number>> = new Map(); | 
					
						
							| 
									
										
										
										
											2019-04-04 11:41:52 -07:00
										 |  |  |     const sanitizerNameByContext: Map<number, Function> = new Map([ | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |       [SecurityContext.URL, ɵɵsanitizeUrl], [SecurityContext.RESOURCE_URL, ɵɵsanitizeResourceUrl] | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |     ]); | 
					
						
							|  |  |  |     Object.keys(schema).forEach(key => { | 
					
						
							|  |  |  |       const context = schema[key]; | 
					
						
							|  |  |  |       if (context === SecurityContext.URL || SecurityContext.RESOURCE_URL) { | 
					
						
							|  |  |  |         const [tag, prop] = key.split('|'); | 
					
						
							|  |  |  |         const contexts = contextsByProp.get(prop) || new Set<number>(); | 
					
						
							|  |  |  |         contexts.add(context); | 
					
						
							|  |  |  |         contextsByProp.set(prop, contexts); | 
					
						
							|  |  |  |         // check only in case a prop can be a part of both URL contexts
 | 
					
						
							|  |  |  |         if (contexts.size === 2) { | 
					
						
							| 
									
										
										
										
											2019-04-04 11:41:52 -07:00
										 |  |  |           expect(getUrlSanitizer(tag, prop)).toEqual(sanitizerNameByContext.get(context) !); | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should sanitize resourceUrls via sanitizeUrlOrResourceUrl', () => { | 
					
						
							|  |  |  |     const ERROR = 'unsafe value used in a resource URL context (see http://g.co/ng/security#xss)'; | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(() => ɵɵsanitizeUrlOrResourceUrl('http://server', 'iframe', 'src')).toThrowError(ERROR); | 
					
						
							|  |  |  |     expect(() => ɵɵsanitizeUrlOrResourceUrl('javascript:true', 'iframe', 'src')) | 
					
						
							|  |  |  |         .toThrowError(ERROR); | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |     expect( | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |         () => ɵɵsanitizeUrlOrResourceUrl( | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |             bypassSanitizationTrustHtml('javascript:true'), 'iframe', 'src')) | 
					
						
							| 
									
										
										
										
											2019-07-31 13:15:50 -07:00
										 |  |  |         .toThrowError(/Required a safe ResourceURL, got a HTML/); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeUrlOrResourceUrl( | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |                bypassSanitizationTrustResourceUrl('javascript:true'), 'iframe', 'src')) | 
					
						
							|  |  |  |         .toEqual('javascript:true'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should sanitize urls via sanitizeUrlOrResourceUrl', () => { | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeUrlOrResourceUrl('http://server', 'a', 'href')).toEqual('http://server'); | 
					
						
							|  |  |  |     expect(ɵɵsanitizeUrlOrResourceUrl(new Wrap('http://server'), 'a', 'href')) | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |         .toEqual('http://server'); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeUrlOrResourceUrl('javascript:true', 'a', 'href')) | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |         .toEqual('unsafe:javascript:true'); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeUrlOrResourceUrl(new Wrap('javascript:true'), 'a', 'href')) | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |         .toEqual('unsafe:javascript:true'); | 
					
						
							| 
									
										
										
										
											2019-07-31 13:15:50 -07:00
										 |  |  |     expect( | 
					
						
							|  |  |  |         () => | 
					
						
							|  |  |  |             ɵɵsanitizeUrlOrResourceUrl(bypassSanitizationTrustHtml('javascript:true'), 'a', 'href')) | 
					
						
							|  |  |  |         .toThrowError(/Required a safe URL, got a HTML/); | 
					
						
							| 
									
										
										
										
											2019-05-17 18:49:21 -07:00
										 |  |  |     expect(ɵɵsanitizeUrlOrResourceUrl(bypassSanitizationTrustUrl('javascript:true'), 'a', 'href')) | 
					
						
							| 
									
										
										
										
											2019-01-03 10:04:06 -08:00
										 |  |  |         .toEqual('javascript:true'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-07-11 10:58:18 -07:00
										 |  |  | }); |