-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support arbitrary attributes on elements with dashes in the tag name. #3067
Support arbitrary attributes on elements with dashes in the tag name. #3067
Conversation
if (value == null) { | ||
return ''; | ||
} | ||
return name + '=' + quoteAttributeValueForBrowser(value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xss?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We call quoteAttributeValueForBrowser, which calls escapeTextContentForBrowser. Is that not good enough?
What are you worried about? Users controlling the property name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah – even if that's not likely to be idiomatic code, it's surprising if an odd attribute name results in a security hole. You can see that we already check the tag name when generating markup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, cool, I'll add an invariant.
076a97a
to
c841cf6
Compare
cc @sebmarkbage |
@@ -235,7 +235,7 @@ ReactDOMComponent.Mixin = { | |||
propValue = CSSPropertyOperations.createMarkupForStyles(propValue); | |||
} | |||
var markup = | |||
DOMPropertyOperations.createMarkupForProperty(propKey, propValue); | |||
DOMPropertyOperations.createMarkupForProperty(this._tag, propKey, propValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is leaking unnecessarily much information to DOMPropertyOperations. All the tag name logic is already in this file.
I'd rather see the switching done in this file where we already have a regexp for tag names. We might as well use that first check to cache if we're a custom element or not. That way you don't have to recheck for every attribute and every update.
If you do the branching in DOM component you can just have a separate methods for createMarkupForCustomAttribute and setValueForCustomAttribute so that we have a separate code path for those. Avoids the boolean-as-argument problem. |
c841cf6
to
2f442e6
Compare
@sebmarkbage better? |
May not be relevant right now, but does this play nice with SVG's |
Yeah, it'll potentially pass additional properties to font-face if they're transferring props, but shouldn't be a huge problem. If anyone is doing that (I think it's relatively rare), SVG should either ignore the additional attributes or give an error message; either way, it sounds like a fine migration story. I suppose we could special case that tag if anyone really cares. I feel like it's not necessary, but @sebmarkbage tends to prefer being super cautious, so I'll let him have the final say. |
We might need to special case it when we support more SVG attributes, but for this case we're already using setAttribute so it should be fine. Don't think people are transferring random props to font-face very often and even if they do, it shouldn't hurt. |
var markup = | ||
DOMPropertyOperations.createMarkupForProperty(propKey, propValue); | ||
var markup = null; | ||
if(this._tag != null && this._tag.indexOf('-') >= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a missing space after if
2f442e6
to
d70f53c
Compare
I don't see a todo item on this PR; am I missing something? Is there a blocking item, or are we just waiting for a CR? |
* @return {?string} Markup string, or null if the property was invalid. | ||
*/ | ||
createMarkupForCustomAttribute: function(name, value) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ on previous line
d70f53c
to
89f9c44
Compare
); | ||
validatedAttributeNameCache[attributeName] = true; | ||
} | ||
return attributeName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we keep this we don't need the return value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a style that allows you to add validation while passing a value through, similar to function chaining (where a builder returns its self). Otherwise, the function is just void, so we don't loose anything by returning the value. This pattern is pretty common in other languages, but we can remove it if it isn't common javascript.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the style but if we don't use it like that, there's no need to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, fixing now.
var validatedAttributeNameCache = {}; | ||
|
||
function validateDangerousAttributeName(attributeName) { | ||
if (!hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hasOwnProperty
doesn't exist here…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
ad30a5a
to
9561a01
Compare
Switched to warn instead of throw for invalid attribute name. |
cc @zpao Anything tasks remaining? |
9561a01
to
90ba511
Compare
@zpao Ping. |
45e7c20
to
2d2468b
Compare
Ping @zpao. |
@@ -17,6 +17,30 @@ var DOMProperty = require('DOMProperty'); | |||
var quoteAttributeValueForBrowser = require('quoteAttributeValueForBrowser'); | |||
var warning = require('warning'); | |||
|
|||
var VALID_ATTRIBUTE_NAME_REGEX = /^[a-zA-Z_][a-zA-Z_\.\-\d]*$/; // Simplified subset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: move comment to own line above
2d2468b
to
b1db817
Compare
@zpao updated. |
👍 |
…ments Support arbitrary attributes on elements with dashes in the tag name.
Support arbitrary attributes on elements with dashes in the tag name.