Browse Source

fix: fix potential xss vulnerability in ssr when using v-bind

dev
Evan You 6 years ago
parent
commit
3d36a443c7
  1. 5
      src/platforms/web/server/modules/attrs.js
  2. 5
      src/platforms/web/server/util.js
  3. 5
      src/server/optimizing-compiler/runtime-helpers.js
  4. 34
      test/ssr/ssr-string.spec.js

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

@ -14,6 +14,8 @@ import {
isFalsyAttrValue isFalsyAttrValue
} from 'web/util/attrs' } from 'web/util/attrs'
import { isSSRUnsafeAttr } from 'web/server/util'
export default function renderAttrs (node: VNodeWithData): string { export default function renderAttrs (node: VNodeWithData): string {
let attrs = node.data.attrs let attrs = node.data.attrs
let res = '' let res = ''
@ -34,6 +36,9 @@ export default function renderAttrs (node: VNodeWithData): string {
} }
for (const key in attrs) { for (const key in attrs) {
if (isSSRUnsafeAttr(key)) {
continue
}
if (key === 'style') { if (key === 'style') {
// leave it to the style module // leave it to the style module
continue continue

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

@ -18,6 +18,11 @@ const isAttr = makeMap(
'target,title,type,usemap,value,width,wrap' 'target,title,type,usemap,value,width,wrap'
) )
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/
export const isSSRUnsafeAttr = (name: string): boolean => {
return unsafeAttrCharRE.test(name)
}
/* istanbul ignore next */ /* istanbul ignore next */
const isRenderableAttr = (name: string): boolean => { const isRenderableAttr = (name: string): boolean => {
return ( return (

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

@ -1,6 +1,6 @@
/* @flow */ /* @flow */
import { escape } from 'web/server/util' import { escape, isSSRUnsafeAttr } from 'web/server/util'
import { isObject, extend } from 'shared/util' import { isObject, extend } from 'shared/util'
import { renderAttr } from 'web/server/modules/attrs' import { renderAttr } from 'web/server/modules/attrs'
import { renderClass } from 'web/util/class' import { renderClass } from 'web/util/class'
@ -109,6 +109,9 @@ function renderStringList (
function renderAttrs (obj: Object): string { function renderAttrs (obj: Object): string {
let res = '' let res = ''
for (const key in obj) { for (const key in obj) {
if (isSSRUnsafeAttr(key)) {
continue
}
res += renderAttr(key, obj[key]) res += renderAttr(key, obj[key])
} }
return res return res

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

@ -929,6 +929,40 @@ describe('SSR: renderToString', () => {
}) })
}) })
it('should prevent xss in attribute names', done => {
renderVmWithOptions({
data: {
xss: {
'foo="bar"></div><script>alert(1)</script>': ''
}
},
template: `
<div v-bind="xss"></div>
`
}, res => {
expect(res).not.toContain(`<script>alert(1)</script>`)
done()
})
})
it('should prevent xss in attribute names (optimized)', done => {
renderVmWithOptions({
data: {
xss: {
'foo="bar"></div><script>alert(1)</script>': ''
}
},
template: `
<div>
<a v-bind="xss">foo</a>
</div>
`
}, res => {
expect(res).not.toContain(`<script>alert(1)</script>`)
done()
})
})
it('should prevent script xss with v-bind object syntax + array value', done => { it('should prevent script xss with v-bind object syntax + array value', done => {
renderVmWithOptions({ renderVmWithOptions({
data: { data: {

Loading…
Cancel
Save