diff --git a/packages/@ember/-internals/glimmer/lib/utils/string.ts b/packages/@ember/-internals/glimmer/lib/utils/string.ts
index 9359687cebc..6f970d8d11b 100644
--- a/packages/@ember/-internals/glimmer/lib/utils/string.ts
+++ b/packages/@ember/-internals/glimmer/lib/utils/string.ts
@@ -4,6 +4,38 @@
import type { SafeString as GlimmerSafeString } from '@glimmer/runtime';
+/**
+ A wrapper around a string that has been marked as safe ("trusted"). **When
+ rendered in HTML, Ember will not perform any escaping.**
+
+ Note:
+
+ 1. This does not *make* the string safe; it means that some code in your
+ application has *marked* it as safe using the `htmlSafe()` function.
+
+ 2. The only public API for getting a `SafeString` is calling `htmlSafe()`. It
+ is *not* user-constructible.
+
+ If a string contains user inputs or other untrusted data, you must sanitize
+ the string before using the `htmlSafe` method. Otherwise your code is
+ vulnerable to [Cross-Site Scripting][xss]. There are many open source
+ sanitization libraries to choose from, both for front end and server-side
+ sanitization.
+
+ [xss]: https://owasp.org/www-community/attacks/DOM_Based_XSS
+
+ ```javascript
+ import { htmlSafe } from '@ember/template';
+
+ let someTrustedOrSanitizedString = "
Hello!
"
+
+ htmlSafe(someTrustedorSanitizedString);
+ ```
+
+ @public
+ @since 4.12.0
+ @class SafeString
+ */
export class SafeString implements GlimmerSafeString {
private __string: string;
@@ -11,10 +43,24 @@ export class SafeString implements GlimmerSafeString {
this.__string = string;
}
+ /**
+ Get the string back to use as a string.
+
+ @public
+ @method toString
+ @returns The string marked as trusted
+ */
toString(): string {
return `${this.__string}`;
}
+ /**
+ Get the wrapped string as HTML to use without escaping.
+
+ @public
+ @method toHTML
+ @returns string
+ */
toHTML(): string {
return this.toString();
}
@@ -115,8 +161,8 @@ export function htmlSafe(str: string): SafeString {
```javascript
import { htmlSafe, isHTMLSafe } from '@ember/template';
- var plainString = 'plain string',
- safeString = htmlSafe('someValue
');
+ let plainString = 'plain string';
+ let safeString = htmlSafe('someValue
');
isHTMLSafe(plainString); // false
isHTMLSafe(safeString); // true
diff --git a/packages/@ember/string/index.ts b/packages/@ember/string/index.ts
index 7f845c66a95..ec975da09c9 100644
--- a/packages/@ember/string/index.ts
+++ b/packages/@ember/string/index.ts
@@ -290,7 +290,7 @@ export function htmlSafe(str: string): SafeString {
return internalHtmlSafe(str);
}
-export function isHTMLSafe(str: any | null | undefined): str is SafeString {
+export function isHTMLSafe(str: unknown): str is SafeString {
deprecateImportFromString('isHTMLSafe');
return internalIsHtmlSafe(str);