Skip to content

Commit c28f792

Browse files
committedAug 1, 2018
fix: fix potential xss vulnerability in ssr
1 parent 2534219 commit c28f792

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed
 

‎src/platforms/web/server/modules/attrs.js

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
isFalsyAttrValue
1515
} from 'web/util/attrs'
1616

17+
import { isSSRUnsafeAttr } from 'web/server/util'
18+
1719
export default function renderAttrs (node: VNodeWithData): string {
1820
let attrs = node.data.attrs
1921
let res = ''
@@ -34,6 +36,9 @@ export default function renderAttrs (node: VNodeWithData): string {
3436
}
3537

3638
for (const key in attrs) {
39+
if (isSSRUnsafeAttr(key)) {
40+
continue
41+
}
3742
if (key === 'style') {
3843
// leave it to the style module
3944
continue

‎src/platforms/web/server/util.js

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ const isAttr = makeMap(
1818
'target,title,type,usemap,value,width,wrap'
1919
)
2020

21+
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/
22+
export const isSSRUnsafeAttr = name => {
23+
return unsafeAttrCharRE.test(name)
24+
}
25+
2126
/* istanbul ignore next */
2227
const isRenderableAttr = (name: string): boolean => {
2328
return (

‎src/server/optimizing-compiler/runtime-helpers.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* @flow */
22

3-
import { escape } from 'web/server/util'
3+
import { escape, isSSRUnsafeAttr } from 'web/server/util'
44
import { isObject, extend } from 'shared/util'
55
import { renderAttr } from 'web/server/modules/attrs'
66
import { renderClass } from 'web/util/class'
@@ -109,6 +109,9 @@ function renderStringList (
109109
function renderAttrs (obj: Object): string {
110110
let res = ''
111111
for (const key in obj) {
112+
if (isSSRUnsafeAttr(key)) {
113+
continue
114+
}
112115
res += renderAttr(key, obj[key])
113116
}
114117
return res

‎test/ssr/ssr-string.spec.js

+34
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,40 @@ describe('SSR: renderToString', () => {
929929
})
930930
})
931931

932+
it('should prevent xss in attribute names', done => {
933+
renderVmWithOptions({
934+
data: {
935+
xss: {
936+
'foo="bar"></div><script>alert(1)</script>': ''
937+
}
938+
},
939+
template: `
940+
<div v-bind="xss"></div>
941+
`
942+
}, res => {
943+
expect(res).not.toContain(`<script>alert(1)</script>`)
944+
done()
945+
})
946+
})
947+
948+
it('should prevent xss in attribute names (optimized)', done => {
949+
renderVmWithOptions({
950+
data: {
951+
xss: {
952+
'foo="bar"></div><script>alert(1)</script>': ''
953+
}
954+
},
955+
template: `
956+
<div>
957+
<a v-bind="xss">foo</a>
958+
</div>
959+
`
960+
}, res => {
961+
expect(res).not.toContain(`<script>alert(1)</script>`)
962+
done()
963+
})
964+
})
965+
932966
it('should prevent script xss with v-bind object syntax + array value', done => {
933967
renderVmWithOptions({
934968
data: {

0 commit comments

Comments
 (0)