Просмотр исходного кода

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

Evan You 8 лет назад
Родитель
Сommit
3d36a443c7

+ 5 - 0
src/platforms/web/server/modules/attrs.js

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

+ 5 - 0
src/platforms/web/server/util.js

@@ -18,6 +18,11 @@ const isAttr = makeMap(
   '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 */
 const isRenderableAttr = (name: string): boolean => {
   return (

+ 4 - 1
src/server/optimizing-compiler/runtime-helpers.js

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

+ 34 - 0
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 => {
     renderVmWithOptions({
       data: {