Skip to content

Enhance Vue Router useRoute query support and documentation#22209

Open
adrienpessu wants to merge 12 commits into
github:mainfrom
adrienpessu:main
Open

Enhance Vue Router useRoute query support and documentation#22209
adrienpessu wants to merge 12 commits into
github:mainfrom
adrienpessu:main

Conversation

@adrienpessu

@adrienpessu adrienpessu commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Enhance Vue Router useRoute query support and Vue Composition API flow modeling

What we now detect as sources

  • useRoute().query — the query object returned by Vue Router's useRoute() Composition API is now recognized as a client-side remote flow source (threat model: remote). Previously only the Options-API currentRoute / navigation-guard routes (to.query, from.query) were modeled.

The problem

Modern Vue apps built with the Composition API read untrusted URL data via const route = useRoute(); route.query.x. CodeQL did not model useRoute(), so query parameters read this way were not tracked as sources, causing missed DOM-based XSS and other client-side taint findings.

In addition, values passed through Vue's core reactivity helpers (ref, shallowRef, toRef, reactive, computed) were not propagated, so taint was lost as soon as data flowed through these wrappers.

The fix

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

  1. useRoute() source — added router.getMember("useRoute").getACall() to the Vue Router remote-source modeling.
  2. Composition API flow summaries — added a VueCompositionApiSummary (SummarizedCallable) modeling data/taint flow through:
    • ref / shallowRef: Argument[0]ReturnValue.Member[value] (value-preserving)
    • toRef: Argument[0]ReturnValue.Member[value] (taint)
    • reactive: Argument[0]ReturnValue (taint)
    • computed: Argument[0].ReturnValueReturnValue.Member[value] (value-preserving)

Also documented under supported frameworks (vue-router) plus a minorAnalysis change note.

The tests

  • router.js — imports useRoute and adds useRoute().query; tests.expected now lists it under both remoteFlowSource and threatModelSource (remote).
  • tst.js — adds sink(Vue.ref(source(...)).value) cases for all five helpers.
  • tests.ql — new TestConfig with compositionApiDataFlow / compositionApiTaintFlow query predicates (sourcesink), verifying value-flow for ref/shallowRef/computed and taint-flow additionally for toRef/reactive.

@adrienpessu
adrienpessu requested a review from a team as a code owner July 16, 2026 18:01
Copilot AI review requested due to automatic review settings July 16, 2026 18:01
@adrienpessu
adrienpessu requested a review from a team as a code owner July 16, 2026 18:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enhances Vue analysis for Composition API flow and Vue Router route-query sources.

Changes:

  • Models flow through five Vue reactivity helpers.
  • Recognizes useRoute().query as remote input.
  • Expands tests and release documentation.
Show a summary per file
File Description
javascript/ql/lib/semmle/javascript/frameworks/Vue.qll Adds Composition API summaries and useRoute tracking.
javascript/ql/test/library-tests/frameworks/Vue/tst.js Adds helper-flow test cases.
javascript/ql/test/library-tests/frameworks/Vue/tests.ql Adds data-flow and taint queries.
javascript/ql/test/library-tests/frameworks/Vue/tests.expected Records expected analysis results.
javascript/ql/test/library-tests/frameworks/Vue/router.js Adds a useRoute().query fixture.
javascript/ql/lib/change-notes/2026-07-16-vue-router-useRoute-query.md Documents the analysis improvements.
change-notes/1.26/analysis-javascript.md Lists vue-router support.

Review details

  • Files reviewed: 7/7 changed files
  • Comments generated: 2
  • Review effort level: Medium


sink(Vue.ref(source("ref")).value);
sink(Vue.shallowRef(source("shallowRef")).value);
sink(Vue.toRef(source("toRef")).value);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot implement this fix

sink(Vue.shallowRef(source("shallowRef")).value);
sink(Vue.toRef(source("toRef")).value);
sink(Vue.reactive(source("reactive")));
sink(Vue.computed(() => source("computed")).value);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot implement this fix

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 7/7 changed files
  • Comments generated: 2
  • Review effort level: Low


sink(Vue.ref(source("ref")).value);
sink(Vue.shallowRef(source("shallowRef")).value);
sink(Vue.toRef(source("toRef")).value);
sink(Vue.shallowRef(source("shallowRef")).value);
sink(Vue.toRef(source("toRef")).value);
sink(Vue.reactive(source("reactive")));
sink(Vue.computed(() => source("computed")).value);
adrienpessu and others added 2 commits July 17, 2026 15:27
Make `toRef` value-preserving and model the `computed` object overload
so `.value` flow is exercised for both `computed` API shapes.

`computed` is moved into the `vue.model.yml` data extension because the
object overload requires callback flow synthesis that a hand-written
`SummarizedCallable` cannot provide.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5c95b651-1e79-499e-9e11-e09065b14aa9
…-tests

Add Vue toRef value-flow and computed object-overload tests

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Medium


sink(Vue.ref(source("ref")).value);
sink(Vue.shallowRef(source("shallowRef")).value);
sink(Vue.toRef(source("toRef")).value);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants