Skip to content

Commit cc4fa60

Browse files
committed
Patch attribute name vulnerability.
1 parent 8ac9a63 commit cc4fa60

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ export default function renderToString(vnode, context, opts, inner, isSvgMode) {
113113
let name = attrs[i],
114114
v = attributes[name];
115115
if (name==='children') continue;
116+
117+
if (name.match(/[\s\n\/='"\0<>]/)) continue;
118+
116119
if (!(opts && opts.allAttributes) && (name==='key' || name==='ref')) continue;
117120

118121
if (name==='className') {

test/render.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,35 @@ describe('render', () => {
5656
expect(render(<div foo={0} />)).to.equal(`<div foo="0"></div>`);
5757
});
5858

59+
describe('attribute name sanitization', () => {
60+
it('should omit attributes with invalid names', () => {
61+
let rendered = render(h('div', {
62+
'<a': '1',
63+
'a>': '1',
64+
'foo"bar': '1',
65+
'"hello"': '1'
66+
}));
67+
expect(rendered).to.equal(`<div></div>`);
68+
});
69+
70+
it('should mitigate attribute name injection', () => {
71+
let rendered = render(h('div', {
72+
'></div><script>alert("hi")</script>': '',
73+
'foo onclick': 'javascript:alert()',
74+
a: 'b'
75+
}));
76+
expect(rendered).to.equal(`<div a="b"></div>`);
77+
});
78+
79+
it('should allow emoji attribute names', () => {
80+
let rendered = render(h('div', {
81+
'a;b': '1',
82+
'a🧙‍b': '1'
83+
}));
84+
expect(rendered).to.equal(`<div a;b="1" a🧙‍b="1"></div>`);
85+
});
86+
});
87+
5988
it('should collapse collapsible attributes', () => {
6089
let rendered = render(<div class="" style="" foo={true} bar />),
6190
expected = `<div class style foo bar></div>`;

0 commit comments

Comments
 (0)