Skip to content

Commit

Permalink
refactor(VSelect): render highlight with vnodes instead of innerHTML
Browse files Browse the repository at this point in the history
Prevents possible XSS vulnerability
  • Loading branch information
KaelWD committed Sep 8, 2022
1 parent ade1434 commit 4468e3c
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 25 deletions.
25 changes: 10 additions & 15 deletions packages/vuetify/src/components/VSelect/VSelectList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ import Colorable from '../../mixins/colorable'
import Themeable from '../../mixins/themeable'

// Helpers
import {
escapeHTML,
getPropertyFromItem,
} from '../../util/helpers'
import { getPropertyFromItem } from '../../util/helpers'

// Types
import mixins from '../../util/mixins'
Expand Down Expand Up @@ -113,17 +110,17 @@ export default mixins(Colorable, Themeable).extend({
genFilteredText (text: string) {
text = text || ''

if (!this.searchInput || this.noFilter) return escapeHTML(text)
if (!this.searchInput || this.noFilter) return text

const { start, middle, end } = this.getMaskedCharacters(text)

return `${escapeHTML(start)}${this.genHighlight(middle)}${escapeHTML(end)}`
return [start, this.genHighlight(middle), end]
},
genHeader (props: { [key: string]: any }): VNode {
return this.$createElement(VSubheader, { props }, props.header)
},
genHighlight (text: string): string {
return `<span class="v-list-item__mask">${escapeHTML(text)}</span>`
genHighlight (text: string) {
return this.$createElement('span', { staticClass: 'v-list__tile__mask' }, text)
},
getMaskedCharacters (text: string): {
start: string
Expand Down Expand Up @@ -202,13 +199,11 @@ export default mixins(Colorable, Themeable).extend({
: scopedSlot
},
genTileContent (item: any, index = 0): VNode {
const innerHTML = this.genFilteredText(this.getText(item))

return this.$createElement(VListItemContent,
[this.$createElement(VListItemTitle, {
domProps: { innerHTML },
})]
)
return this.$createElement(VListItemContent, [
this.$createElement(VListItemTitle, [
this.genFilteredText(this.getText(item)),
]),
])
},
hasItem (item: object) {
return this.parsedItems.indexOf(this.getValue(item)) > -1
Expand Down
10 changes: 0 additions & 10 deletions packages/vuetify/src/util/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,6 @@ export function getZIndex (el?: Element | null): number {
return index
}

const tagsToReplace = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
} as any

export function escapeHTML (str: string): string {
return str.replace(/[&<>]/g, tag => tagsToReplace[tag] || tag)
}

export function filterObjectOnKeys<T, K extends keyof T> (obj: T, keys: K[]): { [N in K]: T[N] } {
const filtered = {} as { [N in K]: T[N] }

Expand Down

0 comments on commit 4468e3c

Please sign in to comment.