Repository navigation
Expand file tree
/
Copy pathdom_sanitization_service.ts
More file actions
231 lines (214 loc) Β· 8.43 KB
/
Copy pathdom_sanitization_service.ts
File metadata and controls
231 lines (214 loc) Β· 8.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/**
* @license
* Copyright Google LLC 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.dev/license
*/
import {DOCUMENT} from '@angular/common';
import {
Ι΅_sanitizeHtml as _sanitizeHtml,
Ι΅_sanitizeUrl as _sanitizeUrl,
Ι΅allowSanitizationBypassAndThrow as allowSanitizationBypassOrThrow,
Ι΅bypassSanitizationTrustHtml as bypassSanitizationTrustHtml,
Ι΅bypassSanitizationTrustResourceUrl as bypassSanitizationTrustResourceUrl,
Ι΅bypassSanitizationTrustScript as bypassSanitizationTrustScript,
Ι΅bypassSanitizationTrustStyle as bypassSanitizationTrustStyle,
Ι΅bypassSanitizationTrustUrl as bypassSanitizationTrustUrl,
Ι΅BypassType as BypassType,
forwardRef,
inject,
Injectable,
Ι΅RuntimeError as RuntimeError,
Sanitizer,
SecurityContext,
Service,
Ι΅unwrapSafeValue as unwrapSafeValue,
Ι΅XSS_SECURITY_URL as XSS_SECURITY_URL,
} from '@angular/core';
import {RuntimeErrorCode} from '../errors';
export {SecurityContext};
/**
* Marker interface for a value that's safe to use in a particular context.
*
* @publicApi
*/
export interface SafeValue {}
/**
* Marker interface for a value that's safe to use as HTML.
*
* @publicApi
*/
export interface SafeHtml extends SafeValue {}
/**
* Marker interface for a value that's safe to use as style (CSS).
*
* @publicApi
*/
export interface SafeStyle extends SafeValue {}
/**
* Marker interface for a value that's safe to use as JavaScript.
*
* @publicApi
*/
export interface SafeScript extends SafeValue {}
/**
* Marker interface for a value that's safe to use as a URL linking to a document.
*
* @publicApi
*/
export interface SafeUrl extends SafeValue {}
/**
* Marker interface for a value that's safe to use as a URL to load executable code from.
*
* @publicApi
*/
export interface SafeResourceUrl extends SafeValue {}
/**
* DomSanitizer helps preventing Cross Site Scripting Security bugs (XSS) by sanitizing
* values to be safe to use in the different DOM contexts.
*
* For example, when binding a URL in an `<a [href]="someValue">` hyperlink, `someValue` will be
* sanitized so that an attacker cannot inject e.g. a `javascript:` URL that would execute code on
* the website.
*
* In specific situations, it might be necessary to disable sanitization, for example if the
* application genuinely needs to produce a `javascript:` style link with a dynamic value in it.
* Users can bypass security by constructing a value with one of the `bypassSecurityTrust...`
* methods, and then binding to that value from the template.
*
* These situations should be very rare, and extraordinary care must be taken to avoid creating a
* Cross Site Scripting (XSS) security bug!
*
* When using `bypassSecurityTrust...`, make sure to call the method as early as possible and as
* close as possible to the source of the value, to make it easy to verify no security bug is
* created by its use.
*
* It is not required (and not recommended) to bypass security if the value is safe, e.g. a URL that
* does not start with a suspicious protocol, or an HTML snippet that does not contain dangerous
* code. The sanitizer leaves safe values intact.
*
* @security Calling any of the `bypassSecurityTrust...` APIs disables Angular's built-in
* sanitization for the value passed in. Carefully check and audit all values and code paths going
* into this call. Make sure any user data is appropriately escaped for this security context.
* For more detail, see the [Security Guide](https://g.co/ng/security).
*
* @publicApi
*/
@Injectable({providedIn: 'root', useExisting: forwardRef(() => DomSanitizerImpl)})
export abstract class DomSanitizer implements Sanitizer {
/**
* Gets a safe value from either a known safe value or a value with unknown safety.
*
* If the given value is already a `SafeValue`, this method returns the unwrapped value.
* If the security context is HTML and the given value is a plain string, this method
* sanitizes the string, removing any potentially unsafe content.
* For any other security context, this method throws an error if provided
* with a plain string.
*/
abstract sanitize(context: SecurityContext, value: SafeValue | string | null): string | null;
/**
* Bypass security and trust the given value to be safe HTML. Only use this when the bound HTML
* is unsafe (e.g. contains `<script>` tags) and the code should be executed. The sanitizer will
* leave safe HTML intact, so in most situations this method should not be used.
*
* **WARNING:** calling this method with untrusted user data exposes your application to XSS
* security risks!
*/
abstract bypassSecurityTrustHtml(value: string): SafeHtml;
/**
* Bypass security and trust the given value to be safe style value (CSS).
*
* **WARNING:** calling this method with untrusted user data exposes your application to XSS
* security risks!
*/
abstract bypassSecurityTrustStyle(value: string): SafeStyle;
/**
* Bypass security and trust the given value to be safe JavaScript.
*
* **WARNING:** calling this method with untrusted user data exposes your application to XSS
* security risks!
*/
abstract bypassSecurityTrustScript(value: string): SafeScript;
/**
* Bypass security and trust the given value to be a safe style URL, i.e. a value that can be used
* in hyperlinks or `<img src>`.
*
* **WARNING:** calling this method with untrusted user data exposes your application to XSS
* security risks!
*/
abstract bypassSecurityTrustUrl(value: string): SafeUrl;
/**
* Bypass security and trust the given value to be a safe resource URL, i.e. a location that may
* be used to load executable code from, like `<script src>`, or `<iframe src>`.
*
* **WARNING:** calling this method with untrusted user data exposes your application to XSS
* security risks!
*/
abstract bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl;
}
@Service()
export class DomSanitizerImpl extends DomSanitizer {
private _doc = inject(DOCUMENT);
override sanitize(ctx: SecurityContext, value: SafeValue | string | null): string | null {
if (value == null) return null;
switch (ctx) {
case SecurityContext.NONE:
return value as string;
case SecurityContext.HTML:
if (allowSanitizationBypassOrThrow(value, BypassType.Html)) {
return unwrapSafeValue(value);
}
return _sanitizeHtml(this._doc, String(value)).toString();
case SecurityContext.STYLE:
if (allowSanitizationBypassOrThrow(value, BypassType.Style)) {
return unwrapSafeValue(value);
}
return value as string;
case SecurityContext.SCRIPT:
if (allowSanitizationBypassOrThrow(value, BypassType.Script)) {
return unwrapSafeValue(value);
}
throw new RuntimeError(
RuntimeErrorCode.SANITIZATION_UNSAFE_SCRIPT,
(typeof ngDevMode === 'undefined' || ngDevMode) &&
'unsafe value used in a script context',
);
case SecurityContext.URL:
if (allowSanitizationBypassOrThrow(value, BypassType.Url)) {
return unwrapSafeValue(value);
}
return _sanitizeUrl(String(value));
case SecurityContext.RESOURCE_URL:
if (allowSanitizationBypassOrThrow(value, BypassType.ResourceUrl)) {
return unwrapSafeValue(value);
}
throw new RuntimeError(
RuntimeErrorCode.SANITIZATION_UNSAFE_RESOURCE_URL,
(typeof ngDevMode === 'undefined' || ngDevMode) &&
`unsafe value used in a resource URL context (see ${XSS_SECURITY_URL})`,
);
default:
throw new RuntimeError(
RuntimeErrorCode.SANITIZATION_UNEXPECTED_CTX,
(typeof ngDevMode === 'undefined' || ngDevMode) &&
`Unexpected SecurityContext ${ctx} (see ${XSS_SECURITY_URL})`,
);
}
}
override bypassSecurityTrustHtml(value: string): SafeHtml {
return bypassSanitizationTrustHtml(value);
}
override bypassSecurityTrustStyle(value: string): SafeStyle {
return bypassSanitizationTrustStyle(value);
}
override bypassSecurityTrustScript(value: string): SafeScript {
return bypassSanitizationTrustScript(value);
}
override bypassSecurityTrustUrl(value: string): SafeUrl {
return bypassSanitizationTrustUrl(value);
}
override bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl {
return bypassSanitizationTrustResourceUrl(value);
}
}