Skip to content

Commit 859783c

Browse files
committed
JS: Support [(ngModel)]
1 parent d55c68c commit 859783c

File tree

4 files changed

+18
-2
lines changed

4 files changed

+18
-2
lines changed

javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ private boolean isAngularTemplateAttributeName(String name) {
186186

187187
/** Attribute names that look valid in HTML or in one of the template languages we support, like Vue and Angular. */
188188
private static final Pattern VALID_ATTRIBUTE_NAME =
189-
Pattern.compile("[*:@]?\\[?\\(?[\\w:_\\-.]+\\]?\\)?");
189+
Pattern.compile("[*:@]?\\[?\\(?[\\w:_\\-.]+\\)?\\]?");
190190

191191
/** List of HTML attributes whose value is interpreted as JavaScript. */
192192
private static final Pattern JS_ATTRIBUTE =

javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,16 @@ module XssThroughDom {
270270
this = getSelectionCall(DataFlow::TypeTracker::end()).getAMethodCall("toString")
271271
}
272272
}
273+
274+
/**
275+
* A source of DOM input originating from an Angular two-way data binding.
276+
*/
277+
private class AngularNgModelSource extends Source {
278+
AngularNgModelSource() {
279+
exists(Angular2::ComponentClass component, string fieldName |
280+
fieldName = component.getATemplateElement().getAttributeByName("[(ngModel)]").getValue() and
281+
this = component.getFieldInputNode(fieldName)
282+
)
283+
}
284+
}
273285
}

javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
edges
2+
| angular.ts:12:5:12:23 | field: string = ""; | angular.ts:27:24:27:33 | this.field | provenance | |
23
| angular.ts:23:24:23:33 | form.value | angular.ts:23:24:23:37 | form.value.foo | provenance | |
34
| forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values | provenance | |
45
| forms.js:9:31:9:36 | values | forms.js:9:31:9:40 | values.foo | provenance | |
@@ -43,10 +44,12 @@ edges
4344
| xss-through-dom.js:154:25:154:27 | msg | xss-through-dom.js:155:27:155:29 | msg | provenance | |
4445
| xss-through-dom.js:159:34:159:52 | $("textarea").val() | xss-through-dom.js:154:25:154:27 | msg | provenance | |
4546
nodes
47+
| angular.ts:12:5:12:23 | field: string = ""; | semmle.label | field: string = ""; |
4648
| angular.ts:15:24:15:41 | event.target.value | semmle.label | event.target.value |
4749
| angular.ts:19:24:19:35 | target.value | semmle.label | target.value |
4850
| angular.ts:23:24:23:33 | form.value | semmle.label | form.value |
4951
| angular.ts:23:24:23:37 | form.value.foo | semmle.label | form.value.foo |
52+
| angular.ts:27:24:27:33 | this.field | semmle.label | this.field |
5053
| forms.js:8:23:8:28 | values | semmle.label | values |
5154
| forms.js:9:31:9:36 | values | semmle.label | values |
5255
| forms.js:9:31:9:40 | values.foo | semmle.label | values.foo |
@@ -132,6 +135,7 @@ subpaths
132135
| angular.ts:15:24:15:41 | event.target.value | angular.ts:15:24:15:41 | event.target.value | angular.ts:15:24:15:41 | event.target.value | $@ is reinterpreted as HTML without escaping meta-characters. | angular.ts:15:24:15:41 | event.target.value | DOM text |
133136
| angular.ts:19:24:19:35 | target.value | angular.ts:19:24:19:35 | target.value | angular.ts:19:24:19:35 | target.value | $@ is reinterpreted as HTML without escaping meta-characters. | angular.ts:19:24:19:35 | target.value | DOM text |
134137
| angular.ts:23:24:23:37 | form.value.foo | angular.ts:23:24:23:33 | form.value | angular.ts:23:24:23:37 | form.value.foo | $@ is reinterpreted as HTML without escaping meta-characters. | angular.ts:23:24:23:33 | form.value | DOM text |
138+
| angular.ts:27:24:27:33 | this.field | angular.ts:12:5:12:23 | field: string = ""; | angular.ts:27:24:27:33 | this.field | $@ is reinterpreted as HTML without escaping meta-characters. | angular.ts:12:5:12:23 | field: string = ""; | DOM text |
135139
| forms.js:9:31:9:40 | values.foo | forms.js:8:23:8:28 | values | forms.js:9:31:9:40 | values.foo | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:8:23:8:28 | values | DOM text |
136140
| forms.js:12:31:12:40 | values.bar | forms.js:11:24:11:29 | values | forms.js:12:31:12:40 | values.bar | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:11:24:11:29 | values | DOM text |
137141
| forms.js:25:23:25:34 | values.email | forms.js:24:15:24:20 | values | forms.js:25:23:25:34 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:24:15:24:20 | values | DOM text |

javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/angular.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ export class Foo {
2424
}
2525

2626
useField() {
27-
document.write(this.field); // NOT OK [INCONSISTENCY]
27+
document.write(this.field); // NOT OK
2828
}
2929
}

0 commit comments

Comments
 (0)