Skip to content

Commit bd21395

Browse files
authored
Merge pull request #5 from adrienpessu/adrienpessu-solid-eureka
JS: Model Vue Composition API and vue-router useRoute sources via data extensions
2 parents 148d9cc + b5136b6 commit bd21395

4 files changed

Lines changed: 15 additions & 37 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
22
category: minorAnalysis
33
---
4-
* The query parameter of Vue Router's `useRoute()` Composition API is now recognized as a client-side remote flow source.
4+
* The route object returned by Vue Router's `useRoute()` Composition API is now recognized as a client-side remote flow source, covering its `query`, `params`, `path`, `fullPath`, and `hash` members. These members are additionally reported under the corresponding `browser-url-query`, `browser-url-path`, and `browser-url-fragment` threat models.
55
* Added flow models for Vue's `ref`, `shallowRef`, `toRef`, `reactive`, and `computed` Composition API helpers.

javascript/ql/lib/ext/vue.model.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
extensions:
2+
- addsTo:
3+
pack: codeql/javascript-all
4+
extensible: sourceModel
5+
data:
6+
# `useRoute()` — Vue Router's Composition API returns a route object whose URL-derived
7+
# members are client-side remote flow sources.
8+
- ["vue-router", "Member[useRoute].ReturnValue.Member[params,path,fullPath]", "browser-url-path"]
9+
- ["vue-router", "Member[useRoute].ReturnValue.Member[query]", "browser-url-query"]
10+
- ["vue-router", "Member[useRoute].ReturnValue.Member[hash]", "browser-url-fragment"]
211
- addsTo:
312
pack: codeql/javascript-all
413
extensible: summaryModel
514
data:
15+
# `ref`, `shallowRef`, `toRef` — the wrapped argument flows to `.value`.
16+
- ["vue", "Member[ref,shallowRef,toRef]", "Argument[0]", "ReturnValue.Member[value]", "value"]
17+
# `reactive` — the wrapped argument taints the returned reactive object.
18+
- ["vue", "Member[reactive]", "Argument[0]", "ReturnValue", "taint"]
619
# `computed(() => ...)` — function overload: the getter's return value flows to `.value`.
720
- ["vue", "Member[computed]", "Argument[0].ReturnValue", "ReturnValue.Member[value]", "value"]
821
# `computed({ get() { ... } })` — object overload: the `get` getter's return value flows to `.value`.

javascript/ql/lib/semmle/javascript/frameworks/Vue.qll

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -35,40 +35,6 @@ module Vue {
3535
result = any(GlobalVueEntryPoint e).getANode()
3636
}
3737

38-
/**
39-
* Models data flow through Vue Composition API helpers.
40-
*
41-
* Note that `computed` is not modeled here but in the `vue.model.yml` data
42-
* extension, because its object overload (`computed({ get() { ... } })`)
43-
* requires callback flow synthesis that data extensions support but a
44-
* hand-written `SummarizedCallable` does not.
45-
*/
46-
overlay[local?]
47-
private class VueCompositionApiSummary extends DataFlow::SummarizedCallable::Range {
48-
string name;
49-
50-
VueCompositionApiSummary() {
51-
name = ["ref", "shallowRef", "toRef", "reactive"] and
52-
this = "vue." + name
53-
}
54-
55-
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
56-
name = ["ref", "shallowRef", "toRef"] and
57-
input = "Argument[0]" and
58-
output = "ReturnValue.Member[value]" and
59-
preservesValue = true
60-
or
61-
name = "reactive" and
62-
input = "Argument[0]" and
63-
output = "ReturnValue" and
64-
preservesValue = false
65-
}
66-
67-
override DataFlow::InvokeNode getACall() {
68-
result = API::moduleImport("vue").getMember(name).getACall()
69-
}
70-
}
71-
7238
/**
7339
* Gets a reference to the 'Vue' object.
7440
*/
@@ -686,8 +652,6 @@ module Vue {
686652
t.start() and
687653
(
688654
exists(API::Node router | router = API::moduleImport("vue-router") |
689-
result = router.getMember("useRoute").getACall()
690-
or
691655
result = router.getInstance().getMember("currentRoute").asSource()
692656
or
693657
result =

javascript/ql/test/library-tests/frameworks/Vue/tests.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ threatModelSource
240240
| router.js:39:5:39:14 | from.query | remote |
241241
| router.js:43:5:43:12 | to.query | remote |
242242
| router.js:44:5:44:14 | from.query | remote |
243+
| router.js:47:1:47:16 | useRoute().query | browser-url-query |
243244
| router.js:47:1:47:16 | useRoute().query | remote |
244245
| single-component-file-1.vue:7:45:7:54 | this.input | view-component-input |
245246
| single-file-component-3-script.js:5:42:5:51 | this.input | view-component-input |

0 commit comments

Comments
 (0)