diff --git a/packages/core/src/util/dom.ts b/packages/core/src/util/dom.ts index 805daa5a926b..f55098583e12 100644 --- a/packages/core/src/util/dom.ts +++ b/packages/core/src/util/dom.ts @@ -6,15 +6,27 @@ * found in the LICENSE file at https://angular.io/license */ -const END_COMMENT = /-->/g; -const END_COMMENT_ESCAPED = '-\u200B-\u200B>'; +/** + * Disallowed strings in the comment. + * + * see: https://html.spec.whatwg.org/multipage/syntax.html#comments + */ +const COMMENT_DISALLOWED = /^>|^->||--!>|)/; +const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B'; /** - * Escape the content of the strings so that it can be safely inserted into a comment node. + * Escape the content of comment strings so that it can be safely inserted into a comment node. * * The issue is that HTML does not specify any way to escape comment end text inside the comment. - * `". -->`. Above the `"-->"` is meant to be text not - * an end to the comment. This can be created programmatically through DOM APIs. + * Consider: `" or + * "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This + * can be created programmatically through DOM APIs. (`` and replace - * it with `-_-_>` where the `_` is a zero width space `\u200B`. The result is that if a comment - * contains `-->` text it will render normally but it will not cause the HTML parser to close the - * comment. + * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and + * surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a + * comment contains any of the comment start/end delimiters (such as `` or `--!>`) the + * text it will render normally but it will not cause the HTML parser to close/open the comment. * - * @param value text to make safe for comment node by escaping the comment close character sequence + * @param value text to make safe for comment node by escaping the comment open/close character + * sequence. */ export function escapeCommentText(value: string): string { - return value.replace(END_COMMENT, END_COMMENT_ESCAPED); + return value.replace( + COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED)); } \ No newline at end of file diff --git a/packages/core/test/acceptance/security_spec.ts b/packages/core/test/acceptance/security_spec.ts index 0376dcc1cf71..afc8b9ccd40d 100644 --- a/packages/core/test/acceptance/security_spec.ts +++ b/packages/core/test/acceptance/security_spec.ts @@ -11,24 +11,33 @@ import {TestBed} from '@angular/core/testing'; describe('comment node text escaping', () => { - it('should not be possible to do XSS through comment reflect data', () => { - @Component({template: `