Intent to Implement and Ship: CSS advanced attr() function

507 views
Skip to first unread message

Xiaocheng Hu

unread,
May 14, 2020, 6:29:12 PM5/14/20
to blink-dev

Contact emails

xiaoc...@chromium.org


Explainer

https://developer.mozilla.org/en-US/docs/Web/CSS/attr#Examples



Design docs/spec

Specification: https://drafts.csswg.org/css-values-4/#attr-notation


https://bit.ly/2YZ0egU


TAG review

https://github.com/w3ctag/design-reviews/issues/513


Summary

Implement the augmentation to attr() specified in CSS Level 4, namely, allowing various types (besides <string>) and usage in all CSS properties (besides pseudo-element 'content').


Note: CSS Level 4 has made substantial revisions to attr() compared to Level 3 to ease the implementation. We'll follow CSS4.


Motivation

This is a highly requested feature, with 77 stars at crbug.com/246571. We also want to keep it considered in the CR period by adding the first implementation.


Risks


Interoperability and Compatibility

No browser has implemented this feature yet. Even though there's no negative signals from other browsers, there's still a minimal interoperability risk that we end up the only implementation.


Firefox: No public signals (https://bugzilla.mozilla.org/show_bug.cgi?id=435426)

Edge: No public signals

Safari: No public signals (https://bugs.webkit.org/show_bug.cgi?id=26609)

Web developers: No signals



Will this feature be supported on all six Blink platforms (Windows, Mac, Linux,

Chrome OS, Android, and Android WebView)?

Yes


Is this feature fully tested by web-platform-tests?

No

There's some WPT coverage as for May 2020:


https://wpt.fyi/results/css/css-values?label=master&label=experimental&aligned&q=attr


We will introduce more tests: https://bugs.chromium.org/p/chromium/issues/detail?id=1081995


Tracking bug

https://bugs.chromium.org/p/chromium/issues/detail?id=246571


Link to entry on the Chrome Platform Status

https://chromestatus.com/feature/4680129030651904



This intent message was generated by Chrome Platform Status.

Mike West

unread,
May 15, 2020, 8:25:42 AM5/15/20
to Xiaocheng Hu, blink-dev
Hello!

The security and privacy considerations section of the spec (https://drafts.csswg.org/css-values-4/#sec-pri) doesn't account for exfiltration concerns like those raised in https://bugzilla.mozilla.org/show_bug.cgi?id=435426#c37 (and variants thereof outlined in https://dl.acm.org/doi/pdf/10.1145/2382196.2382276 and https://speakerdeck.com/mikewest/xss-no-the-other-s-cssconf-eu-2013).

I'm also curious about how it would interact with the nonce-exfiltration mitigations we put into HTML: https://html.spec.whatwg.org/multipage/urls-and-fetching.html#nonce-attributes.

-mike


--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAFqEGhbR2mhM5DYUj52qCB957y%2BbpZDb67qqumrd2w9JTAGHFw%40mail.gmail.com.

Xiaocheng Hu

unread,
May 15, 2020, 3:01:53 PM5/15/20
to Mike West, jacka...@gmail.com, Xiaocheng Hu, blink-dev
+jack...@gmail.com spec editor for the security concerns

Artur Janc

unread,
May 17, 2020, 5:18:08 AM5/17/20
to blink-dev, xiaoc...@chromium.org, blink-dev, mk...@chromium.org, jacka...@gmail.com
I'd like to +1 what Mike said and specifically point out the effects of the new `attr()` on the fairly large number of sites that use nonce-based Content Security Policy which controls scripts, but allows inline CSS (https://csp.withgoogle.com/docs/strict-csp.html). The capability to directly read/use the values arbitrary attributes would bypass the protections of such policies and allow exfiltrating sensitive parts of a document (e.g. CSRF tokens, passwords) even in the case of a limited CSS injection or a partial HTML/CSS sanitizer bypass.

It seems like it would be good to first spend some time figuring out the security story for this feature... 

Anders Hartvoll Ruud

unread,
May 18, 2020, 4:30:01 AM5/18/20
to Artur Janc, blink-dev, xiaoc...@chromium.org, mk...@chromium.org, jacka...@gmail.com
Do we have (or need) a plan re. current in-the-wild usage of attr() in the content property?

<style>
  div::before { content: attr(text) " World"; }
  div::before { content: attr(text) 1px; }
</style>
<div text="Hello"></div>


In the above example, the current behavior in Chrome is to display "Hello World", since the second declaration isn't accepted by the parser. With the new behavior, the second declaration is accepted by the parser, but becomes invalid at computed-value time.


PhistucK

unread,
May 18, 2020, 5:39:53 AM5/18/20
to Anders Hartvoll Ruud, Artur Janc, blink-dev, xiaoc...@chromium.org, mk...@chromium.org, jacka...@gmail.com
How will implementing this feature affect the parsing of div::before { content: attr(text) 1px; }?
This sees like invalid syntax regardless of this feature (and I never saw personally)...

Also, what is the original intention of div::before { content: attr(text) 1px; }?

PhistucK


Anders Hartvoll Ruud

unread,
May 18, 2020, 6:34:25 AM5/18/20
to PhistucK, Artur Janc, blink-dev, xiaoc...@chromium.org, mk...@chromium.org, jacka...@gmail.com
On Mon, May 18, 2020 at 11:39 AM PhistucK <phis...@gmail.com> wrote:
How will implementing this feature affect the parsing of div::before { content: attr(text) 1px; }?
This sees like invalid syntax regardless of this feature (and I never saw personally)...

Also, what is the original intention of div::before { content: attr(text) 1px; }?

It is indeed invalid currently. The difference is when it's invalid.

Currently declaration 2 is thrown out parse-time, meaning that declaration 1 will still apply. With the new attr() behavior, declaration 2 is accepted parse-time, meaning 1 is "forgotten". Computed-value time, we substitute attr(text) with "Hello", and attempt to parse content:"Hello" 1px. This is not valid grammar for content, hence it's invalid at computed-value time, which produces unset behavior.

PhistucK

unread,
May 18, 2020, 7:07:25 AM5/18/20
to Anders Hartvoll Ruud, Artur Janc, blink-dev, xiaoc...@chromium.org, mk...@chromium.org, jacka...@gmail.com
I still do not get it... Is it because before this feature, attr(...) would be replaced at parse time?
(I see that it is re-computed if you change the content of the attribute, which seems to contradict that it is being replaced at parse time)

PhistucK

Anders Hartvoll Ruud

unread,
May 18, 2020, 7:56:20 AM5/18/20
to PhistucK, Artur Janc, blink-dev, xiaoc...@chromium.org, mk...@chromium.org, jacka...@gmail.com
On Mon, May 18, 2020 at 1:07 PM PhistucK <phis...@gmail.com> wrote:
I still do not get it... Is it because before this feature, attr(...) would be replaced at parse time?
(I see that it is re-computed if you change the content of the attribute, which seems to contradict that it is being replaced at parse time)

 
It is not replaced parse-time, before or after this feature.

Perhaps it's helpful to use var() as an example instead:

div::before { content: var(--x) 1px; }

The mere presence of var() here means the value is valid parse-time, even though it's obvious (to humans) that it ultimately can't result in anything valid. When the parser discovers a var() in a value, it does not interpret the value further, but instead defers the "true" parsing against the grammar of 'content' to computed-value time.

This feature basically changes attr() to behave like var(), except it substitutes an attribute value instead of a custom property value. The mere presence of attr() will make any (almost) any declaration valid at parse-time.

This is not how attr() currently works, i.e. it doesn't have this "any declaration valid" magic. It currently works more like a regular CSS function, such as calc(), linear-gradient(), etc. See also the content's grammar, which explicitly allows attr().

PhistucK

unread,
May 18, 2020, 8:07:11 AM5/18/20
to Anders Hartvoll Ruud, Artur Janc, blink-dev, xiaoc...@chromium.org, mk...@chromium.org, jacka...@gmail.com
Thank you for the clarification!

PhistucK

Xiaocheng Hu

unread,
May 18, 2020, 4:35:44 PM5/18/20
to PhistucK, Anders Hartvoll Ruud, Artur Janc, blink-dev, xiaoc...@chromium.org, mk...@chromium.org, jacka...@gmail.com
Regarding the security concerns, it appears to me that this doesn't introduce extra security risks?

We don't need attr() to exfiltrate sensitive data of a document. The attribute selector already allows that (I learned it from this article).

So should it be a blocking issue if this feature doesn't introduce new vulnerabilities?

---

Regarding Ander's question on the existing usage in pseudo-element content... Maybe we should measure the frequency of such invalid values?

If such invalid usage is rare, we should be able to safely switch it to the new spec. Otherwise we might need to special case it.

Mike West

unread,
May 19, 2020, 8:22:46 AM5/19/20
to Xiaocheng Hu, PhistucK, Anders Hartvoll Ruud, Artur Janc, blink-dev, jacka...@gmail.com
On Mon, May 18, 2020 at 10:35 PM Xiaocheng Hu <xiaoc...@chromium.org> wrote:
Regarding the security concerns, it appears to me that this doesn't introduce extra security risks?

We don't need attr() to exfiltrate sensitive data of a document. The attribute selector already allows that (I learned it from this article).

So should it be a blocking issue if this feature doesn't introduce new vulnerabilities?

The attacks discussed here and above rely on iterative, brute-force searching for an attribute's value by exfiltrating one character at a time with prefix selectors, possibly relying on some server-side smarts to generate new rules as it goes. It seems different in kind to inject a single rule that can exfiltrate an attribute directly, worth considering in itself even if we don't make additional changes to CSS.

At a minimum, it seems reasonable to think about limiting `attr()` (and other attribute selectors?) from accessing content in some particularly interesting attributes (`nonce`, `value`, anything in a `hidden` form control)? Or, better yet, limiting them to a subset of specially-prefixed attributes?

-mike

Xiaocheng Hu

unread,
May 19, 2020, 7:51:36 PM5/19/20
to Mike West, Xiaocheng Hu, PhistucK, Anders Hartvoll Ruud, Artur Janc, blink-dev, jacka...@gmail.com
I've filed https://github.com/w3c/csswg-drafts/issues/5092 regarding the security concerns.

sligh...@chromium.org

unread,
May 21, 2020, 3:11:20 PM5/21/20
to blink-dev, mk...@google.com, xiaoc...@chromium.org, phis...@gmail.com, and...@chromium.org, a...@google.com, jacka...@gmail.com
Hey Xiaocheng,

Per a conversation at the API OWNERs meeting today, might I suggest we split this into an I2P/I2I and a separate I2S? What do you think?

Regards
PhistucK



PhistucK


To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

Xiaocheng Hu

unread,
May 26, 2020, 3:12:55 PM5/26/20
to sligh...@chromium.org, blink-dev, Mike West, Xiaocheng Hu, PhistucK, Anders Hartvoll Ruud, Artur Janc, jacka...@gmail.com
Sure, I'll do a split.

PhistucK



PhistucK


--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
Reply all
Reply to author
Forward
0 new messages