From 09e4c78b0f766aa14d0863d77d0465c4fe63f7df Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:33:42 +0000 Subject: [PATCH 01/18] New XSS sink - writing to innerHTML using the Angular Renderer2 API --- .../dataflow/DomBasedXssCustomizations.qll | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll index 72d9ae4e55a6..270d58d4fa7e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll @@ -251,6 +251,26 @@ module DomBasedXss { } } + /** + * A write to the `innerHTML` property of a DOM element, viewed as an XSS sink. + * + * Uses the Angular Renderer2 API, instead of the default `Element.innerHTML` property. + */ + class AngularRender2SetPropertyInnerHtmlSink extends Sink { + AngularRender2SetPropertyInnerHtmlSink() { + exists(API::CallNode setProperty | + setProperty = + API::moduleImport("@angular/core") + .getMember("Renderer2") + .getInstance() + .getMember("setProperty") + .getACall() and + this = setProperty.getParameter(2).asSink() and + setProperty.getParameter(1).asSink().asExpr().(StringLiteral).getValue() = "innerHTML" + ) + } + } + /** * A value being piped into the `safe` pipe in a template file, * disabling subsequent HTML escaping. From 0f648223562adaaffa6eea006263ee51a7cfcfb2 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:34:15 +0000 Subject: [PATCH 02/18] New remote source - reading from an @Input() decorated class member --- .../security/dataflow/RemoteFlowSources.qll | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll index aad00b2d22e5..a41b8d8062d3 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -184,3 +184,36 @@ private class ExternalRemoteFlowSource extends RemoteFlowSource { override string getSourceType() { result = ap.getSourceType() } } + +// Angular @Input() decorator on a member declaration. +class InputMember extends MemberDeclaration { + InputMember() { + exists(Decorator decorator, Expr expr | + decorator.getElement() = this + and decorator.getExpression() = expr + and expr.(CallExpr).getCallee().(VarRef).getName() = "Input" + ) + } +} + +// Use of an Angular @Input() member. +class InputMemberUse extends DataFlow::Node { + InputMemberUse() { + exists(InputMember member, string memberName, ThisExpr ta, FieldAccess fa | + memberName = member.getName() + and fa.getBase() = ta + and fa.getPropertyName() = memberName + and this.asExpr() = fa + ) + } +} + +private class AngularInputUse extends RemoteFlowSource { + AngularInputUse() { + exists( InputMemberUse inputUse | + this = inputUse + ) + } + + override string getSourceType() { result = "Angular @Input()" } +} \ No newline at end of file From 477391787679b63672c597aacb530b8926150e8d Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:43:00 +0000 Subject: [PATCH 03/18] Formatting --- .../dataflow/DomBasedXssCustomizations.qll | 2 +- .../security/dataflow/RemoteFlowSources.qll | 30 ++++++++----------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll index 270d58d4fa7e..ab5bff5d73e9 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll @@ -253,7 +253,7 @@ module DomBasedXss { /** * A write to the `innerHTML` property of a DOM element, viewed as an XSS sink. - * + * * Uses the Angular Renderer2 API, instead of the default `Element.innerHTML` property. */ class AngularRender2SetPropertyInnerHtmlSink extends Sink { diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll index a41b8d8062d3..6b1748996e3b 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -189,31 +189,27 @@ private class ExternalRemoteFlowSource extends RemoteFlowSource { class InputMember extends MemberDeclaration { InputMember() { exists(Decorator decorator, Expr expr | - decorator.getElement() = this - and decorator.getExpression() = expr - and expr.(CallExpr).getCallee().(VarRef).getName() = "Input" + decorator.getElement() = this and + decorator.getExpression() = expr and + expr.(CallExpr).getCallee().(VarRef).getName() = "Input" ) } } // Use of an Angular @Input() member. class InputMemberUse extends DataFlow::Node { - InputMemberUse() { - exists(InputMember member, string memberName, ThisExpr ta, FieldAccess fa | - memberName = member.getName() - and fa.getBase() = ta - and fa.getPropertyName() = memberName - and this.asExpr() = fa - ) - } + InputMemberUse() { + exists(InputMember member, string memberName, ThisExpr ta, FieldAccess fa | + memberName = member.getName() and + fa.getBase() = ta and + fa.getPropertyName() = memberName and + this.asExpr() = fa + ) + } } private class AngularInputUse extends RemoteFlowSource { - AngularInputUse() { - exists( InputMemberUse inputUse | - this = inputUse - ) - } + AngularInputUse() { exists(InputMemberUse inputUse | this = inputUse) } override string getSourceType() { result = "Angular @Input()" } -} \ No newline at end of file +} From 4891c1e5fe132df851c4ed333176047bab24883b Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:50:47 +0000 Subject: [PATCH 04/18] Added QLdoc and simplified QL in source class --- .../security/dataflow/RemoteFlowSources.qll | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll index 6b1748996e3b..2c16406cac49 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -185,7 +185,9 @@ private class ExternalRemoteFlowSource extends RemoteFlowSource { override string getSourceType() { result = ap.getSourceType() } } -// Angular @Input() decorator on a member declaration. +/** + * Angular @Input() decorator on a member declaration. + */ class InputMember extends MemberDeclaration { InputMember() { exists(Decorator decorator, Expr expr | @@ -196,7 +198,9 @@ class InputMember extends MemberDeclaration { } } -// Use of an Angular @Input() member. +/** + * Use of an Angular @Input() member, modelled as `InputMember`. + */ class InputMemberUse extends DataFlow::Node { InputMemberUse() { exists(InputMember member, string memberName, ThisExpr ta, FieldAccess fa | @@ -208,8 +212,11 @@ class InputMemberUse extends DataFlow::Node { } } +/** + * A remote flow source that is a member of an Angular component class. + */ private class AngularInputUse extends RemoteFlowSource { - AngularInputUse() { exists(InputMemberUse inputUse | this = inputUse) } + AngularInputUse() { this instanceof InputMemberUse } override string getSourceType() { result = "Angular @Input()" } } From 712870000307ce275360bd9a05ebf72106294c77 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Fri, 3 Jan 2025 17:02:55 +0000 Subject: [PATCH 05/18] Simplified AngularInputUse class --- .../javascript/security/dataflow/RemoteFlowSources.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll index 2c16406cac49..60031d3a94bb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -186,7 +186,7 @@ private class ExternalRemoteFlowSource extends RemoteFlowSource { } /** - * Angular @Input() decorator on a member declaration. + * An Angular @Input() decorator on a member declaration. */ class InputMember extends MemberDeclaration { InputMember() { @@ -199,7 +199,7 @@ class InputMember extends MemberDeclaration { } /** - * Use of an Angular @Input() member, modelled as `InputMember`. + * A use of an Angular @Input() member, modeled as `InputMember`. */ class InputMemberUse extends DataFlow::Node { InputMemberUse() { @@ -215,8 +215,8 @@ class InputMemberUse extends DataFlow::Node { /** * A remote flow source that is a member of an Angular component class. */ -private class AngularInputUse extends RemoteFlowSource { - AngularInputUse() { this instanceof InputMemberUse } +private class AngularInputUse extends RemoteFlowSource, InputMemberUse { + AngularInputUse() { this = this } override string getSourceType() { result = "Angular @Input()" } } From aba8be2902b207cd8639882b3ad7b68e0598bc63 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Fri, 3 Jan 2025 17:07:35 +0000 Subject: [PATCH 06/18] Changelog for Angular source/sink update --- .../ql/lib/change-notes/2025-01-03-angular-source-sink.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md diff --git a/javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md b/javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md new file mode 100644 index 000000000000..4ba7122ecccb --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md @@ -0,0 +1,5 @@ +--- +category: majorAnalysis +--- +* Added new remote source from class members decorated with `@Input()` +* Added new XSS sink where `InnerHTML` is assigned to with the Angular Renderer2 API From 8dac00aa832c55bd91d54544b310ad208810da7f Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Mon, 6 Jan 2025 15:43:47 +0000 Subject: [PATCH 07/18] Change from getParameter() to getArgument() --- .../javascript/security/dataflow/DomBasedXssCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll index ab5bff5d73e9..8a3e66e8e806 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll @@ -266,7 +266,7 @@ module DomBasedXss { .getMember("setProperty") .getACall() and this = setProperty.getParameter(2).asSink() and - setProperty.getParameter(1).asSink().asExpr().(StringLiteral).getValue() = "innerHTML" + setProperty.getArgument(1).getStringValue() = "innerHTML" ) } } From e414b8c5be491c957f93526224b51a07c5a73f44 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:51:35 +0000 Subject: [PATCH 08/18] Remove @Input() decorated members as remote sources, in favour of a later Threat Model --- .../security/dataflow/RemoteFlowSources.qll | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll index 60031d3a94bb..aad00b2d22e5 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -184,39 +184,3 @@ private class ExternalRemoteFlowSource extends RemoteFlowSource { override string getSourceType() { result = ap.getSourceType() } } - -/** - * An Angular @Input() decorator on a member declaration. - */ -class InputMember extends MemberDeclaration { - InputMember() { - exists(Decorator decorator, Expr expr | - decorator.getElement() = this and - decorator.getExpression() = expr and - expr.(CallExpr).getCallee().(VarRef).getName() = "Input" - ) - } -} - -/** - * A use of an Angular @Input() member, modeled as `InputMember`. - */ -class InputMemberUse extends DataFlow::Node { - InputMemberUse() { - exists(InputMember member, string memberName, ThisExpr ta, FieldAccess fa | - memberName = member.getName() and - fa.getBase() = ta and - fa.getPropertyName() = memberName and - this.asExpr() = fa - ) - } -} - -/** - * A remote flow source that is a member of an Angular component class. - */ -private class AngularInputUse extends RemoteFlowSource, InputMemberUse { - AngularInputUse() { this = this } - - override string getSourceType() { result = "Angular @Input()" } -} From 6fb201372bc95eee4f797d437cb1de6d9fdd18ab Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:51:59 +0000 Subject: [PATCH 09/18] Update changelog note to remove new source --- javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md | 1 - 1 file changed, 1 deletion(-) diff --git a/javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md b/javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md index 4ba7122ecccb..609642c25b4a 100644 --- a/javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md +++ b/javascript/ql/lib/change-notes/2025-01-03-angular-source-sink.md @@ -1,5 +1,4 @@ --- category: majorAnalysis --- -* Added new remote source from class members decorated with `@Input()` * Added new XSS sink where `InnerHTML` is assigned to with the Angular Renderer2 API From 322c731ac339b6843f4ed58e8f55f8e9d5b28c21 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:52:38 +0000 Subject: [PATCH 10/18] Attempt at AttributeDefinition to generalise Angular Renderer2 support --- .../frameworks/AngularJS/AngularJSCore.qll | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 1a6d11cd7534..2778a9f84d78 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -1032,3 +1032,37 @@ private class BindCall extends DataFlow::PartialInvokeNode::Range, DataFlow::Cal result = this.getArgument(0) } } + +/** + * A DOM attribute write, using the AngularJS Renderer2 API: a call to `Renderer2.setProperty`. + */ +private class AngularRenderer2AttributeDefinition extends DOM::AttributeDefinition { + DataFlow::Node propertyNode; + DataFlow::Node valueNode; + DataFlow::Node elementNode; + + AngularRenderer2AttributeDefinition() { + exists(API::CallNode setProperty | + setProperty = + API::moduleImport("@angular/core") + .getMember("Renderer2") + .getInstance() + .getMember("setProperty") + .getACall() and + elementNode = setProperty.getArgument(0) and + propertyNode = setProperty.getArgument(1) and + valueNode = setProperty.getArgument(2) and + this = setProperty.asExpr() + ) + } + + override string getName() { result = propertyNode.getStringValue() } + + // override DOM::ElementDefinition getElement() { /* TODO */ } + + DataFlow::Node getElementNode() { result = elementNode } + + override DataFlow::Node getValueNode() { result = valueNode } + + //override predicate mayHaveTemplateValue() { /* TODO */ } +} From 820fe6cd042385058f1a25f0b22fc389078098de Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:59:04 +0000 Subject: [PATCH 11/18] Formatting --- .../semmle/javascript/frameworks/AngularJS/AngularJSCore.qll | 2 -- 1 file changed, 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 2778a9f84d78..2b4826c1529b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -1059,10 +1059,8 @@ private class AngularRenderer2AttributeDefinition extends DOM::AttributeDefiniti override string getName() { result = propertyNode.getStringValue() } // override DOM::ElementDefinition getElement() { /* TODO */ } - DataFlow::Node getElementNode() { result = elementNode } override DataFlow::Node getValueNode() { result = valueNode } - //override predicate mayHaveTemplateValue() { /* TODO */ } } From 45301186810dc0b41b596fbda246d0ef00b41189 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:33:31 +0000 Subject: [PATCH 12/18] Comment out hardcoded definition of sink --- .../dataflow/DomBasedXssCustomizations.qll | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll index 8a3e66e8e806..026cf47106fd 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll @@ -251,25 +251,25 @@ module DomBasedXss { } } - /** - * A write to the `innerHTML` property of a DOM element, viewed as an XSS sink. - * - * Uses the Angular Renderer2 API, instead of the default `Element.innerHTML` property. - */ - class AngularRender2SetPropertyInnerHtmlSink extends Sink { - AngularRender2SetPropertyInnerHtmlSink() { - exists(API::CallNode setProperty | - setProperty = - API::moduleImport("@angular/core") - .getMember("Renderer2") - .getInstance() - .getMember("setProperty") - .getACall() and - this = setProperty.getParameter(2).asSink() and - setProperty.getArgument(1).getStringValue() = "innerHTML" - ) - } - } + // /** + // * A write to the `innerHTML` property of a DOM element, viewed as an XSS sink. + // * + // * Uses the Angular Renderer2 API, instead of the default `Element.innerHTML` property. + // */ + // class AngularRender2SetPropertyInnerHtmlSink extends Sink { + // AngularRender2SetPropertyInnerHtmlSink() { + // exists(API::CallNode setProperty | + // setProperty = + // API::moduleImport("@angular/core") + // .getMember("Renderer2") + // .getInstance() + // .getMember("setProperty") + // .getACall() and + // this = setProperty.getParameter(2).asSink() and + // setProperty.getArgument(1).getStringValue() = "innerHTML" + // ) + // } + // } /** * A value being piped into the `safe` pipe in a template file, From 2dc9e7bab78a67b0eb9e9129a7a5b05edb9c72e6 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Wed, 8 Jan 2025 16:36:10 +0000 Subject: [PATCH 13/18] Moved def from AngularJSCore to Angular2 --- .../semmle/javascript/frameworks/Angular2.qll | 32 +++++++++++++++++++ .../frameworks/AngularJS/AngularJSCore.qll | 32 ------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index 16430ff0475a..ba0f339f594e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -554,4 +554,36 @@ module Angular2 { this = API::Node::ofType("@angular/core", "ElementRef").getMember("nativeElement").asSource() } } + + /** + * A DOM attribute write, using the AngularJS Renderer2 API: a call to `Renderer2.setProperty`. + */ + class AngularRenderer2AttributeDefinition extends DOM::AttributeDefinition { + DataFlow::Node propertyNode; + DataFlow::Node valueNode; + DataFlow::Node elementNode; + + AngularRenderer2AttributeDefinition() { + exists(API::CallNode setProperty | + setProperty = + API::moduleImport("@angular/core") + .getMember("Renderer2") + .getInstance() + .getMember("setProperty") + .getACall() and + elementNode = setProperty.getArgument(0) and + propertyNode = setProperty.getArgument(1) and + valueNode = setProperty.getArgument(2) and + this = setProperty.asExpr() + ) + } + + override string getName() { result = propertyNode.getStringValue() } + + // override DOM::ElementDefinition getElement() { /* TODO */ } + DataFlow::Node getElementNode() { result = elementNode } + + override DataFlow::Node getValueNode() { result = valueNode } + //override predicate mayHaveTemplateValue() { /* TODO */ } + } } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 2b4826c1529b..1a6d11cd7534 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -1032,35 +1032,3 @@ private class BindCall extends DataFlow::PartialInvokeNode::Range, DataFlow::Cal result = this.getArgument(0) } } - -/** - * A DOM attribute write, using the AngularJS Renderer2 API: a call to `Renderer2.setProperty`. - */ -private class AngularRenderer2AttributeDefinition extends DOM::AttributeDefinition { - DataFlow::Node propertyNode; - DataFlow::Node valueNode; - DataFlow::Node elementNode; - - AngularRenderer2AttributeDefinition() { - exists(API::CallNode setProperty | - setProperty = - API::moduleImport("@angular/core") - .getMember("Renderer2") - .getInstance() - .getMember("setProperty") - .getACall() and - elementNode = setProperty.getArgument(0) and - propertyNode = setProperty.getArgument(1) and - valueNode = setProperty.getArgument(2) and - this = setProperty.asExpr() - ) - } - - override string getName() { result = propertyNode.getStringValue() } - - // override DOM::ElementDefinition getElement() { /* TODO */ } - DataFlow::Node getElementNode() { result = elementNode } - - override DataFlow::Node getValueNode() { result = valueNode } - //override predicate mayHaveTemplateValue() { /* TODO */ } -} From 4b57d5feb2a346e79a71e8e6d60e3b66609f2509 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Wed, 8 Jan 2025 16:36:46 +0000 Subject: [PATCH 14/18] Added XSS sink for innerHTML/outerHTML using new Angular attribute def --- .../dataflow/DomBasedXssCustomizations.qll | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll index 026cf47106fd..e2a785ee4b14 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll @@ -251,25 +251,19 @@ module DomBasedXss { } } - // /** - // * A write to the `innerHTML` property of a DOM element, viewed as an XSS sink. - // * - // * Uses the Angular Renderer2 API, instead of the default `Element.innerHTML` property. - // */ - // class AngularRender2SetPropertyInnerHtmlSink extends Sink { - // AngularRender2SetPropertyInnerHtmlSink() { - // exists(API::CallNode setProperty | - // setProperty = - // API::moduleImport("@angular/core") - // .getMember("Renderer2") - // .getInstance() - // .getMember("setProperty") - // .getACall() and - // this = setProperty.getParameter(2).asSink() and - // setProperty.getArgument(1).getStringValue() = "innerHTML" - // ) - // } - // } + /** + * A write to the `innerHTML` or `outerHTML` property of a DOM element, viewed as an XSS sink. + * + * Uses the Angular Renderer2 API, instead of the default `Element.innerHTML` property. + */ + class AngularRender2SetPropertyInnerHtmlSink2 extends Sink { + AngularRender2SetPropertyInnerHtmlSink2() { + exists(Angular2::AngularRenderer2AttributeDefinition attrDef | + attrDef.getName() = ["innerHTML", "outerHTML"] and + this = attrDef.getValueNode() + ) + } + } /** * A value being piped into the `safe` pipe in a template file, From 98b4c358442cd5dde729eab25c278fbd1c1160b5 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Thu, 9 Jan 2025 17:00:01 +0000 Subject: [PATCH 15/18] Set doc string on getElementNode predicate --- javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index ba0f339f594e..1291477af72b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -580,10 +580,12 @@ module Angular2 { override string getName() { result = propertyNode.getStringValue() } - // override DOM::ElementDefinition getElement() { /* TODO */ } + /** Get the `DataFlow::Node` that is affected by this Attribute Definition. + * + * Defined instead of defining `getElement()`, which requires returning a DOM element defintion, `ElementDefinition`. + */ DataFlow::Node getElementNode() { result = elementNode } override DataFlow::Node getValueNode() { result = valueNode } - //override predicate mayHaveTemplateValue() { /* TODO */ } } } From 62599b2a1256dcc94ddb33825bedb6a71b6f0dd8 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Thu, 9 Jan 2025 17:02:37 +0000 Subject: [PATCH 16/18] Formatted --- javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index 1291477af72b..ba8f2e231219 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -580,8 +580,9 @@ module Angular2 { override string getName() { result = propertyNode.getStringValue() } - /** Get the `DataFlow::Node` that is affected by this Attribute Definition. - * + /** + * Get the `DataFlow::Node` that is affected by this Attribute Definition. + * * Defined instead of defining `getElement()`, which requires returning a DOM element defintion, `ElementDefinition`. */ DataFlow::Node getElementNode() { result = elementNode } From e7881a8c7fd9b2438f6b11e0898e7fcd3ea8f350 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Thu, 9 Jan 2025 17:11:06 +0000 Subject: [PATCH 17/18] Fix typo --- javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index ba8f2e231219..dd71a1cf728b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -583,7 +583,7 @@ module Angular2 { /** * Get the `DataFlow::Node` that is affected by this Attribute Definition. * - * Defined instead of defining `getElement()`, which requires returning a DOM element defintion, `ElementDefinition`. + * Defined instead of defining `getElement()`, which requires returning a DOM element definition, `ElementDefinition`. */ DataFlow::Node getElementNode() { result = elementNode } From b07e801c106b0824e7df3daee127a645cf7674c0 Mon Sep 17 00:00:00 2001 From: aegilops <41705651+aegilops@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:02:45 +0000 Subject: [PATCH 18/18] Add new test for new XSS sink, update `expected` to match --- .../Security/CWE-079/DomBasedXss/Xss.expected | 240 +++++++++--------- .../XssWithAdditionalSources.expected | 211 +++++++-------- .../CWE-079/DomBasedXss/angular2-client.ts | 7 +- 3 files changed, 244 insertions(+), 214 deletions(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected index 9b764729c99d..e1308043db9e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected @@ -25,67 +25,73 @@ nodes | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | -| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | -| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | -| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | -| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | +| angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | +| angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | +| angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | +| angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | +| angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | | angular-tempate-url.js:13:30:13:31 | ev | @@ -1249,44 +1255,51 @@ edges | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:40:44:40:58 | this.router.url | angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | | angular-tempate-url.js:13:30:13:31 | ev | angular-tempate-url.js:14:26:14:27 | ev | | angular-tempate-url.js:13:30:13:31 | ev | angular-tempate-url.js:14:26:14:27 | ev | | angular-tempate-url.js:14:26:14:27 | ev | angular-tempate-url.js:14:26:14:32 | ev.data | @@ -2415,20 +2428,21 @@ edges | addEventListener.js:2:20:2:29 | event.data | addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:29 | event.data | Cross-site scripting vulnerability due to $@. | addEventListener.js:1:43:1:47 | event | user-provided value | | addEventListener.js:6:20:6:23 | data | addEventListener.js:5:43:5:48 | {data} | addEventListener.js:6:20:6:23 | data | Cross-site scripting vulnerability due to $@. | addEventListener.js:5:43:5:48 | {data} | user-provided value | | addEventListener.js:12:24:12:33 | event.data | addEventListener.js:10:21:10:25 | event | addEventListener.js:12:24:12:33 | event.data | Cross-site scripting vulnerability due to $@. | addEventListener.js:10:21:10:25 | event | user-provided value | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | Cross-site scripting vulnerability due to $@. | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | user-provided value | -| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:24:44:24:69 | this.ro ... .params | user-provided value | -| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:25:44:25:74 | this.ro ... yParams | user-provided value | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | Cross-site scripting vulnerability due to $@. | angular2-client.ts:26:44:26:71 | this.ro ... ragment | user-provided value | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | user-provided value | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | user-provided value | -| angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:30:46:30:59 | map.get('foo') | user-provided value | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | Cross-site scripting vulnerability due to $@. | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | user-provided value | -| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:34:44:34:80 | this.ro ... ameters | user-provided value | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | user-provided value | -| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:36:44:36:89 | this.ro ... .params | user-provided value | -| angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:38:44:38:58 | this.router.url | user-provided value | -| angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:40:45:40:59 | this.router.url | user-provided value | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | user-provided value | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | Cross-site scripting vulnerability due to $@. | angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | user-provided value | +| angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:26:44:26:69 | this.ro ... .params | user-provided value | +| angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:27:44:27:74 | this.ro ... yParams | user-provided value | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | angular2-client.ts:28:44:28:71 | this.ro ... ragment | angular2-client.ts:28:44:28:71 | this.ro ... ragment | Cross-site scripting vulnerability due to $@. | angular2-client.ts:28:44:28:71 | this.ro ... ragment | user-provided value | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | user-provided value | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | user-provided value | +| angular2-client.ts:32:46:32:59 | map.get('foo') | angular2-client.ts:32:46:32:59 | map.get('foo') | angular2-client.ts:32:46:32:59 | map.get('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:32:46:32:59 | map.get('foo') | user-provided value | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | angular2-client.ts:35:44:35:74 | this.ro ... 1].path | angular2-client.ts:35:44:35:74 | this.ro ... 1].path | Cross-site scripting vulnerability due to $@. | angular2-client.ts:35:44:35:74 | this.ro ... 1].path | user-provided value | +| angular2-client.ts:36:44:36:82 | this.ro ... eters.x | angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:36:44:36:80 | this.ro ... ameters | user-provided value | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | angular2-client.ts:37:44:37:91 | this.ro ... et('x') | angular2-client.ts:37:44:37:91 | this.ro ... et('x') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:37:44:37:91 | this.ro ... et('x') | user-provided value | +| angular2-client.ts:38:44:38:91 | this.ro ... arams.x | angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:38:44:38:89 | this.ro ... .params | user-provided value | +| angular2-client.ts:40:44:40:58 | this.router.url | angular2-client.ts:40:44:40:58 | this.router.url | angular2-client.ts:40:44:40:58 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:40:44:40:58 | this.router.url | user-provided value | +| angular2-client.ts:42:45:42:59 | this.router.url | angular2-client.ts:42:45:42:59 | this.router.url | angular2-client.ts:42:45:42:59 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:42:45:42:59 | this.router.url | user-provided value | +| angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:43:75:43:105 | this.ro ... yParams | user-provided value | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | user-provided value | | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | angular-tempate-url.js:13:30:13:31 | ev | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | Cross-site scripting vulnerability due to $@. | angular-tempate-url.js:13:30:13:31 | ev | user-provided value | | classnames.js:7:31:7:84 | `` | classnames.js:7:58:7:68 | window.name | classnames.js:7:31:7:84 | `` | Cross-site scripting vulnerability due to $@. | classnames.js:7:58:7:68 | window.name | user-provided value | | classnames.js:8:31:8:85 | `` | classnames.js:8:59:8:69 | window.name | classnames.js:8:31:8:85 | `` | Cross-site scripting vulnerability due to $@. | classnames.js:8:59:8:69 | window.name | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index 185cae0d2d30..3d968b9022a6 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected @@ -25,67 +25,73 @@ nodes | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | -| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | -| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | -| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | -| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | +| angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | +| angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | +| angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | +| angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | +| angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | | angular-tempate-url.js:13:30:13:31 | ev | @@ -1299,44 +1305,51 @@ edges | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | -| angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | -| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | -| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | -| angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | -| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | -| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | -| angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | -| angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | -| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | angular2-client.ts:24:44:24:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:69 | this.ro ... .params | angular2-client.ts:26:44:26:73 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:27:44:27:74 | this.ro ... yParams | angular2-client.ts:27:44:27:78 | this.ro ... ams.foo | +| angular2-client.ts:28:44:28:71 | this.ro ... ragment | angular2-client.ts:28:44:28:71 | this.ro ... ragment | +| angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | angular2-client.ts:29:44:29:82 | this.ro ... ('foo') | +| angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | angular2-client.ts:30:44:30:87 | this.ro ... ('foo') | +| angular2-client.ts:32:46:32:59 | map.get('foo') | angular2-client.ts:32:46:32:59 | map.get('foo') | +| angular2-client.ts:35:44:35:74 | this.ro ... 1].path | angular2-client.ts:35:44:35:74 | this.ro ... 1].path | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:36:44:36:80 | this.ro ... ameters | angular2-client.ts:36:44:36:82 | this.ro ... eters.x | +| angular2-client.ts:37:44:37:91 | this.ro ... et('x') | angular2-client.ts:37:44:37:91 | this.ro ... et('x') | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:89 | this.ro ... .params | angular2-client.ts:38:44:38:91 | this.ro ... arams.x | +| angular2-client.ts:40:44:40:58 | this.router.url | angular2-client.ts:40:44:40:58 | this.router.url | +| angular2-client.ts:42:45:42:59 | this.router.url | angular2-client.ts:42:45:42:59 | this.router.url | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:43:75:43:105 | this.ro ... yParams | angular2-client.ts:43:75:43:109 | this.ro ... ams.foo | +| angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | angular2-client.ts:47:44:47:76 | routeSn ... ('foo') | | angular-tempate-url.js:13:30:13:31 | ev | angular-tempate-url.js:14:26:14:27 | ev | | angular-tempate-url.js:13:30:13:31 | ev | angular-tempate-url.js:14:26:14:27 | ev | | angular-tempate-url.js:14:26:14:27 | ev | angular-tempate-url.js:14:26:14:32 | ev.data | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts index 734a06da3bc1..6d1823c2f601 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, DomSanitizer as DomSanitizer2 } from '@angular/core'; +import { Component, OnInit, DomSanitizer as DomSanitizer2, Renderer2, Inject } from '@angular/core'; import { ɵgetDOM } from '@angular/common'; import { ActivatedRoute, ActivatedRouteSnapshot, Router } from '@angular/router'; import { DomSanitizer } from '@angular/platform-browser'; @@ -15,7 +15,9 @@ export class AppComponent implements OnInit { private route: ActivatedRoute, private sanitizer: DomSanitizer, private router: Router, - private sanitizer2: DomSanitizer2 + private sanitizer2: DomSanitizer2, + private renderer: Renderer2, + @Inject(DOCUMENT) private document: Document ) {} ngOnInit() { @@ -38,6 +40,7 @@ export class AppComponent implements OnInit { this.sanitizer.bypassSecurityTrustHtml(this.router.url); // NOT OK this.sanitizer2.bypassSecurityTrustHtml(this.router.url); // NOT OK + this.renderer.setProperty(this.document.documentElement, 'innerHTML', this.route.snapshot.queryParams.foo); // NOT OK } someMethod(routeSnapshot: ActivatedRouteSnapshot) {