Skip to content

Commit

Permalink
feat: s-data 注释转义特殊字符消除 XSS 隐患
Browse files Browse the repository at this point in the history
  • Loading branch information
liuyue28 authored and harttle committed Dec 4, 2020
1 parent 1a2a675 commit c29c22f
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/target-js/js-emitter.ts
Expand Up @@ -27,7 +27,7 @@ export class JSEmitter extends Emitter {
}

public writeDataComment () {
this.writeHTMLExpression(`"<!--s-data:" + JSON.stringify(${dataAccess(undefined, 'expr', '_.getRootCtx(ctx)')}) + "-->"`)
this.writeHTMLExpression(`"<!--s-data:" + JSON.stringify(${dataAccess(undefined, 'expr', '_.getRootCtx(ctx)')}).replace(/(?<=-)-/g, '\\\\-') + "-->"`)
}

public writeHTMLLiteral (str: string) {
Expand Down
3 changes: 2 additions & 1 deletion src/utils/case.ts
Expand Up @@ -16,7 +16,8 @@ export function parseSanHTML (str: string) {
if (begin !== -1) {
const end = str.indexOf('-->', begin)
if (end !== -1) {
data = JSON.parse(str.slice(begin + 11, end))
// eslint-disable-next-line no-new-func
data = (new Function('return ' + str.slice(begin + 11, end)))()
html = str.slice(0, begin) + str.slice(end + 3)
}
}
Expand Down
13 changes: 13 additions & 0 deletions test/unit/models/san-project.spec.ts
Expand Up @@ -112,6 +112,19 @@ describe('SanProject', function () {
expect(render).toBeInstanceOf(Function)
expect(render({ name: 'Harttle' })).toEqual('<div><!--s-data:{"name":"Harttle"}-->Harttle</div>')
})

it('should escape consecutive hyphen', function () {
const proj = new SanProject()
const componentClass = defineComponent({ template: '<div>{{ a + b + c + d }}</div>' })
const render = proj.compileToRenderer(componentClass)

expect(render({
a: -3,
b: '---',
c: '-',
d: '\\--'
})).toEqual('<div><!--s-data:{"a":-3,"b":"-\\-\\-","c":"-","d":"\\\\-\\-"}-->-3----\\--</div>')
})
})

describe('#compileToSource()', function () {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/target-js/js-emitter.spec.ts
Expand Up @@ -28,7 +28,7 @@ describe('JSEmitter', function () {
it('should write data comment', function () {
emitter.writeDataComment()

expect(emitter.fullText()).toEqual('html += "<!--s-data:" + JSON.stringify(_.getRootCtx(ctx).data) + "-->";\n')
expect(emitter.fullText()).toEqual('html += "<!--s-data:" + JSON.stringify(_.getRootCtx(ctx).data).replace(/(?<=-)-/g, \'\\\\-\') + "-->";\n')
})

describe('write switch case', function () {
Expand Down
4 changes: 4 additions & 0 deletions test/unit/utils/case.spec.ts
Expand Up @@ -40,6 +40,10 @@ describe('utils/case', function () {
expect(data).toEqual({})
expect(html).toEqual('<div><!--s-data:{"foo":"bar"}<input></div>')
})
it('should ignore backslash(\\) when parsing data', () => {
const [data] = parseSanHTML('<div><!--s-data:{"foo":"-\\-"}--><input></div>')
expect(data).toEqual({ foo: '--' })
})
})
describe('.compareSanHTML()', function () {
it('should return true if identical', () => {
Expand Down

0 comments on commit c29c22f

Please sign in to comment.