Skip to content

Commit dc8743b

Browse files
committed
JS: Support [(ngModel)]
1 parent ec4245f commit dc8743b

File tree

4 files changed

+23
-2
lines changed

4 files changed

+23
-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
@@ -249,4 +249,16 @@ module XssThroughDom {
249249
this = getSelectionCall(DataFlow::TypeTracker::end()).getAMethodCall("toString")
250250
}
251251
}
252+
253+
/**
254+
* A source of DOM input originating from an Angular two-way data binding.
255+
*/
256+
private class AngularNgModelSource extends Source {
257+
AngularNgModelSource() {
258+
exists(Angular2::ComponentClass component, string fieldName |
259+
fieldName = component.getATemplateElement().getAttributeByName("[(ngModel)]").getValue() and
260+
this = component.getFieldInputNode(fieldName)
261+
)
262+
}
263+
}
252264
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
nodes
2+
| angular.ts:12:5:12:23 | field: string = ""; |
3+
| angular.ts:12:5:12:23 | field: string = ""; |
24
| angular.ts:15:24:15:41 | event.target.value |
35
| angular.ts:15:24:15:41 | event.target.value |
46
| angular.ts:15:24:15:41 | event.target.value |
@@ -9,6 +11,8 @@ nodes
911
| angular.ts:23:24:23:33 | form.value |
1012
| angular.ts:23:24:23:37 | form.value.foo |
1113
| angular.ts:23:24:23:37 | form.value.foo |
14+
| angular.ts:27:24:27:33 | this.field |
15+
| angular.ts:27:24:27:33 | this.field |
1216
| forms.js:8:23:8:28 | values |
1317
| forms.js:8:23:8:28 | values |
1418
| forms.js:9:31:9:36 | values |
@@ -175,6 +179,10 @@ nodes
175179
| xss-through-dom.js:159:34:159:52 | $("textarea").val() |
176180
| xss-through-dom.js:159:34:159:52 | $("textarea").val() |
177181
edges
182+
| angular.ts:12:5:12:23 | field: string = ""; | angular.ts:27:24:27:33 | this.field |
183+
| angular.ts:12:5:12:23 | field: string = ""; | angular.ts:27:24:27:33 | this.field |
184+
| angular.ts:12:5:12:23 | field: string = ""; | angular.ts:27:24:27:33 | this.field |
185+
| angular.ts:12:5:12:23 | field: string = ""; | angular.ts:27:24:27:33 | this.field |
178186
| angular.ts:15:24:15:41 | event.target.value | angular.ts:15:24:15:41 | event.target.value |
179187
| angular.ts:19:24:19:35 | target.value | angular.ts:19:24:19:35 | target.value |
180188
| angular.ts:23:24:23:33 | form.value | angular.ts:23:24:23:37 | form.value.foo |
@@ -292,6 +300,7 @@ edges
292300
| 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 |
293301
| 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 |
294302
| 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 |
303+
| 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 |
295304
| 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 |
296305
| 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 |
297306
| 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)