Intent to Deprecate and Remove: Block cross-origin <a download>

2,431 views
Skip to first unread message

Jochen Eisinger

unread,
Apr 22, 2017, 6:41:36 AM4/22/17
to blink-dev
joc...@chromium.org https://html.spec.whatwg.org/multipage/semantics.html#the-a-element

I'll send a PR against HTML to include the note from the MDN docs about the download attribute in the spec. To avoid what is essentially user-mediated cross-origin information leakage, Blink will start to ignore the presence of the download attribute on anchor elements with cross origin attributes.
Firefox: Shipped Edge: No public signals Safari: Shipped Web developers: No signals
I'd expect it's low as other browsers already ignore the attribute for cross origin downloads.
None Yes
   https://crbug.com/714373 https://www.chromestatus.com/features/4969697975992320
I'd like to deprecate and remove in M60 assuming that the beta UseCounter numbers aren't scary high.

PhistucK

unread,
Apr 22, 2017, 7:12:34 AM4/22/17
to Jochen Eisinger, blink-dev
Are data URLs considered cross origin when included in <a download> of HTTP(S) pages?


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+unsubscribe@chromium.org.

Jake Archibald

unread,
Apr 22, 2017, 7:26:23 AM4/22/17
to Jochen Eisinger, blink-dev
What data is leaked?

--
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.

Rick Byers

unread,
Apr 22, 2017, 12:04:29 PM4/22/17
to Jake Archibald, Jochen Eisinger, blink-dev
I found some history of the Gecko behavior here.  Makes sense to me.

blob and data URLs are unaffected, right?  It's the blob case that I originally requested the 'download' attribute ~6 years ago when working on Offline GMail ;-)

With Gecko, blink and WebKit all aligned, this should definitely be required by the spec and verified by web-platform-test.  Please share the spec commit on this thread once it's landed.

I assume you will UseCount actual cross-origin downloads (user clicking on such a link), not just the presence of such a link during parsing, right?
  
LGTM1 to deprecate now and remove in M60 after the spec/tests have landed and assuming the beta UseCounter is moderately low (say <0.01% which seems pretty likely to me).

What data is leaked?

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

PhistucK

unread,
Apr 22, 2017, 12:16:11 PM4/22/17
to Rick Byers, Jake Archibald, Jochen Eisinger, blink-dev
Just to be clear, I am not really seeing any attack vector here. The user downloads a cross origin URL - they do not upload it, they download it. The website may as well tell the user to right click and choose "Save link as...". Is there any difference other than the user not knowing that clicking will open a save-as dialog (which is always true, unless the website made it clear to the user)?

Or is this some sort of protecting the user from a multiple-step phishing scam?
"Look, I can see your bank statement (download it here), I know everything about you, give me your password/money!"?
That seems to be far fetched and not very credible (and viewing the statement in a new tab will not make much of a difference to the user, they do not know about the same origin policy or whatever, it is very technical).


PhistucK

Philip Jägenstedt

unread,
Apr 24, 2017, 2:46:33 AM4/24/17
to PhistucK, Rick Byers, Jake Archibald, Jochen Eisinger, blink-dev
https://html.spec.whatwg.org/multipage/semantics.html#as-a-download says "Act in a user-agent-defined manner to safeguard the user from a potentially hostile cross-origin download." and has a big warning that I think explains the risks. Getting rid of the UA-defined behavior would be great.

Per https://url.spec.whatwg.org/#origin both blob: and data: (Otherwise) URLs have opaque origins, and would be considered cross-origin. So these should presumably be exempted from the same-origin check.

LGTM2 to align the spec with Gecko and then matching that.

What data is leaked?

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@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+...@chromium.org.

Jochen Eisinger

unread,
Apr 24, 2017, 2:56:07 AM4/24/17
to Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
Correct, I'd exempt data and blob from the check,

PhistutcK, the risk is indeed from the download being part of a multistep attack, however, we've seen such attacks in the wild, and other browsers already break this step, so aligning with them seems the best option.

Mike West

unread,
Apr 24, 2017, 8:05:22 AM4/24/17
to Jochen Eisinger, Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
Non-OWNER's LGTM; aligning with other vendor's conservative approach to preventing folks from overriding a cross-origin endpoint's decisions about how resources should be persisted on a user's machine seems like a good thing to do. I worry a bit about CDNs and etc, but if the numbers look reasonable, tightening the restrictions here seems like a good idea. Perhaps you could measure a "same-eTLD+1" variant, just in case the base numbers are higher than we'd like?

Carving out `data:` URLs seems reasonable, as the content is controlled by the page doing the downloading.

I don't think you'll need to carve out `blob:` URLs, as they do indeed have an origin (I think Philip might have overlooked their handling in https://url.spec.whatwg.org/#origin). We'd probably want to handle `filesystem:` URLs the same way (even though they're a Chrome-only thing at this point...).

What does Firefox do with `javascript:` URLs? I'd prefer to reject them outright, rather than doing what we do for navigations and downloading the result of executing the JavaScript. It looks like our current behavior does nothing when clicking on `<a download href="javascript:'string'">yay</a>`; let's at least throw a console message?

-mike

What data is leaked?

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.


Boris Zbarsky

unread,
Apr 24, 2017, 9:50:31 AM4/24/17
to Mike West, Jochen Eisinger, Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
On 4/24/17 8:04 AM, Mike West wrote:
> What does Firefox do with `javascript:` URLs?

They're not special in any way. We don't do the extra work needed to
make them not work, so they work.

Note that Firefox supports javascript: in the fetch layer, really, not
in navigation, which is why it Just Works.

-Boris

Boris Zbarsky

unread,
Apr 24, 2017, 11:07:23 AM4/24/17
to Mike West, Jochen Eisinger, Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
On 4/24/17 10:02 AM, Mike West wrote:
> Interesting. What does "supports javascript: in the fetch layer" mean?

It means that Gecko's equivalent of the fetch layer has generic code to
handle a fetch of a javascript: url.

> Does `<img src="javascript:whatever">` execute JavaScript and try to
> load the result as an image? What about `xhr.open()` or `fetch()`?

No. We used to do that, actually, but have turned it off mostly to try
to achieve compat. The javascript: code examines the fetch type, which
in the case of <a download> in Firefox is "navigation", for various
reasons, and only enables execution for navigations.

-Boris

Chris Harrelson

unread,
Apr 25, 2017, 7:35:14 PM4/25/17
to Boris Zbarsky, Mike West, Jochen Eisinger, Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
LGTM3



-Boris

Brian Smith

unread,
Apr 25, 2017, 8:56:36 PM4/25/17
to Mike West, Jochen Eisinger, Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
On Mon, Apr 24, 2017 at 2:04 AM, Mike West <mk...@chromium.org> wrote:
Non-OWNER's LGTM; aligning with other vendor's conservative approach to preventing folks from overriding a cross-origin endpoint's decisions about how resources should be persisted on a user's machine seems like a good thing to do.

Is this about, basically, hotlink protection?

I worry a bit about CDNs and etc, but if the numbers look reasonable, tightening the restrictions here seems like a good idea. Perhaps you could measure a "same-eTLD+1" variant, just in case the base numbers are higher than we'd like?

Carving out `data:` URLs seems reasonable, as the content is controlled by the page doing the downloading.

If this isn't intended to be hotlink protection, then using the same justification that you use for `data:`, shouldn't at least <a download integrity="..."> continue to work?

I thought the idea was exactly to let CDN-based downloads work, without needing to configure the CDN to send Content-Disposition.

What is the actual problem being solved?

Cheers,
Brian
--

Jochen Eisinger

unread,
May 12, 2017, 8:18:41 AM5/12/17
to Brian Smith, Mike West, Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
Sorry for the late reply.

On Wed, Apr 26, 2017 at 2:56 AM Brian Smith <br...@briansmith.org> wrote:
On Mon, Apr 24, 2017 at 2:04 AM, Mike West <mk...@chromium.org> wrote:
Non-OWNER's LGTM; aligning with other vendor's conservative approach to preventing folks from overriding a cross-origin endpoint's decisions about how resources should be persisted on a user's machine seems like a good thing to do.

Is this about, basically, hotlink protection?

I worry a bit about CDNs and etc, but if the numbers look reasonable, tightening the restrictions here seems like a good idea. Perhaps you could measure a "same-eTLD+1" variant, just in case the base numbers are higher than we'd like?

Carving out `data:` URLs seems reasonable, as the content is controlled by the page doing the downloading.

If this isn't intended to be hotlink protection, then using the same justification that you use for `data:`, shouldn't at least <a download integrity="..."> continue to work?
 
Interesting idea, I guess that's worth considering for the SRI spec.


I thought the idea was exactly to let CDN-based downloads work, without needing to configure the CDN to send Content-Disposition.

We can't differentiate between a site that tries to mislead the user, and a site that has a not correctly configured CDN. I think erring on the site of protection users is the right thing here.

Brian Smith

unread,
May 12, 2017, 4:01:40 PM5/12/17
to Jochen Eisinger, Mike West, Philip Jägenstedt, PhistucK, Rick Byers, Jake Archibald, blink-dev
Jochen Eisinger <joc...@chromium.org> wrote:
>> I thought the idea was exactly to let CDN-based downloads work, without
>> needing to configure the CDN to send Content-Disposition.
>
> We can't differentiate between a site that tries to mislead the user, and a
> site that has a not correctly configured CDN.

> I think erring on the site of protection users is the right thing here.

I'm not arguing against protecting users. But I just don't see how
users are actually being protected, especially considering all the
other third-party website content we allow.

Consider the following example.

The first link is an <a download> that links to a third-party website.
This is the thing that would be blocked under this proposal, right?

The second link is a <a download href="data:"> URL constructed from a
script hosted on the very same server we can't trust. But my
understanding is that this link will NOT be blocked under this
proposal, even though the download is hosted on the same evil site.

It seems to me that if third-party JS is allowed then third-party <a
download> should be allowed.

<!DOCTYPE html>
<html>
<title>Third-Party Download Example</title>
<style> a { display: block; padding: 1em }</style>
<h1>Third-Party Download Example</h1>

<a download="secp256r1-seed-EMBARGOED-UNTIL-2017-06-12.txt"
href="https://briansmith.org/demo/secp256r1-seed-EMBARGOED-UNTIL-2017-06-12.txt">secp256r1-seed-EMBARGOED-UNTIL-2017-06-12.txt</a>

<script defer src="https://briansmith.org/demo/third-party-download.js"></script>
</html>

Matthew Menke

unread,
May 12, 2017, 5:33:13 PM5/12/17
to blink-dev, joc...@chromium.org, mk...@chromium.org, foo...@chromium.org, phis...@gmail.com, rby...@chromium.org, jakear...@google.com
Would it make sense to do the whole CORS preflight dance for cross-site <a downloads>, or use anonymous mode / privacy mode / uncredentialed / snufflypuff / whatever we're calling them this week requests?

Matthew Menke

unread,
May 12, 2017, 5:35:54 PM5/12/17
to blink-dev, joc...@chromium.org, mk...@chromium.org, foo...@chromium.org, phis...@gmail.com, rby...@chromium.org, jakear...@google.com
One other question...  If you have a same-site <a download> with cross-site HTTP redirect, I assume those will be blocked, too, so this will need to be implemented browser-side, in the downloads code?

PhistucK

unread,
May 12, 2017, 6:10:46 PM5/12/17
to Matthew Menke, blink-dev, Jochen Eisinger, Mike West, Philip Jägenstedt, Rick Byers, Jake Archibald
Something like <a download="http://cross.origin/" crossorigin="anonymous">?


PhistucK

Jochen Eisinger

unread,
May 16, 2017, 3:43:00 AM5/16/17
to PhistucK, Matthew Menke, blink-dev, Mike West, Philip Jägenstedt, Rick Byers, Jake Archibald
Allowing something like crossorigin="anonymous" would still allow obtaining pre-auth XSRF tokens, so that wouldn't close this particular problem.

ada...@gmail.com

unread,
May 26, 2017, 5:11:15 PM5/26/17
to blink-dev, phis...@gmail.com, mme...@google.com, mk...@chromium.org, foo...@chromium.org, rby...@chromium.org, jakear...@google.com
On my site I have audio files hosted on a separate cookieless CDN domain (from a cloud storage site). There's an <audio> player and an <a download> link. This change will stop all my download links from working.

If there's a legitimate security concern, I understand the need to change, but I'd like there to be a way around it. Ideally, the way around it should only require a client side change (like the crossorigin or integrity attributes described above) as a sever side change would be more complex for me to do. Especially, since the hosted file is used for both downloading and not downloading. I don't want to send an "attachment" header as it is not always intended as a download, sometimes I want the file to be opened by the browser.

Thanks!

Jochen Eisinger

unread,
May 29, 2017, 3:37:47 AM5/29/17
to ada...@gmail.com, blink-dev, phis...@gmail.com, mme...@google.com, mk...@chromium.org, foo...@chromium.org, rby...@chromium.org, jakear...@google.com
Hey,

thanks for the feedback! I've actually put a histogram on the new behavior, and I'm watching how often this triggers to see whether we can actually stick to the new behavior or not (also, different from the initial intent, the target milestone right now is 61).

I wonder whether you could just use a regular <a> link? Wouldn't chrome then download the file anyways, as it can't navigate to it?

best
-jochen

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.

Jochen Eisinger

unread,
May 30, 2017, 10:47:45 AM5/30/17
to ada...@gmail.com, blink-dev, phis...@gmail.com, mme...@google.com, mk...@chromium.org, foo...@chromium.org, rby...@chromium.org, jakear...@google.com
so from the data we got over the weekend it looks like 5% of the downloads are affected by the change, which I'd say is too high.

I'd propose to revert the change and try to figure out a better way - maybe matching the behavior of Firefox exactly would fly..

Rick Byers

unread,
May 30, 2017, 10:56:20 AM5/30/17
to Jochen Eisinger, ada...@gmail.com, blink-dev, PhistucK, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald
Wow!  That's 5% of all <a download> cases, or 5% of ALL downloads?  Either way I agree that's too high (orders of magnitude higher than I had guessed!).

Jochen Eisinger

unread,
May 30, 2017, 11:00:26 AM5/30/17
to Rick Byers, ada...@gmail.com, blink-dev, PhistucK, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald

5% of all downloads if I read the numbers correctly (see the Download.Counts histogram)

Adam Rich

unread,
May 30, 2017, 1:19:21 PM5/30/17
to Jochen Eisinger, Rick Byers, blink-dev, PhistucK, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald
Hi,

In answer to your question:

I wonder whether you could just use a regular <a> link? Wouldn't chrome then download the file anyways, as it can't navigate to it?

Chrome will open an MP3 in its own tab and create a player with controls. This is similar to if you click on a link to an image or a video file. One way we could mitigate my issue would be to create a "Download" button on those pages. I suspect that many people linking directly to an image file or an audio or video file just want to download it. A download button is more user friendly than right-clicking and hitting save-as.

It occurs to me that you might be able to help with your security issue by putting up a dialog to the user. Something like, "This page is trying to download example.pdf from cdn.examplesite.com. Are you sure you want to download this file?".

You could also establish rules on when to show that dialog, factoring in this like:
  • Is the host page HTTPS?
  • Is the downloaded asset on HTTPs?
  • Do they share the same top level domain? secondary domain? etc.?
  • Is the file type a known content file type (e.g. jpeg, mp3, pdf, etc.)?
  • Is the file type a known suspicious file type (e.g. .exe, .js, etc.)?
  • Has the user approved similar requests on this site before?
  • Does the link have a crossorigin attribute?
  • Does the link use SRI with a correct hash of the file?
Thanks,
Adam

         - Adam

PhistucK

unread,
May 31, 2017, 3:35:36 AM5/31/17
to Adam Rich, Jochen Eisinger, Rick Byers, blink-dev, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald

On Tue, May 30, 2017 at 8:18 PM, Adam Rich <ada...@gmail.com> wrote:
One way we could mitigate my issue would be to create a "Download" button on those pages.

​There is a download button on those pages -



PhistucK

Jochen Eisinger

unread,
May 31, 2017, 4:09:25 AM5/31/17
to PhistucK, Adam Rich, Rick Byers, blink-dev, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald
Well, the kind of dialog that we have for downloads is this inline warning that the file might be unwanted.

OTOH, doesn't Firefox already give you this behavior (ignoring the download attribute all together) on your site?

PhistucK

unread,
Jun 16, 2017, 6:56:18 AM6/16/17
to Jochen Eisinger, Adam Rich, Rick Byers, blink-dev, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald
Now that I think about it, if I, as a web developer, use the download attribute - I expect it never to navigate. The download can be blocked (in one way or another), but the page must not be replaced with a different page in that case.

So either emitting an error to the console when the download is blocked (and so seemingly, to the user, doing nothing), or showing a hard safe browsing blockage for the download would make sense to me much more than ignoring the attribute.

Navigating can hard-break existing non-malicious usage and cause data loss for users.


PhistucK

Jochen Eisinger

unread,
Jun 19, 2017, 10:31:26 AM6/19/17
to PhistucK, Adam Rich, Rick Byers, blink-dev, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald
If you never expect it to navigate, you didn't test with Firefox :)

Simon Pieters

unread,
Jun 20, 2017, 8:44:40 AM6/20/17
to PhistucK, Jochen Eisinger, Adam Rich, Rick Byers, blink-dev, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald
On Mon, 19 Jun 2017 16:31:10 +0200, Jochen Eisinger <joc...@chromium.org>
wrote:

> If you never expect it to navigate, you didn't test with Firefox :)

I believe he did. ;-)

https://github.com/w3c/web-platform-tests/pull/6211
https://bugzilla.mozilla.org/show_bug.cgi?id=1373620

--
Simon Pieters
Opera Software

Jochen Eisinger

unread,
Jan 8, 2018, 3:02:47 AM1/8/18
to Simon Pieters, PhistucK, Adam Rich, Rick Byers, blink-dev, Matt Menke, Mike West, Philip Jägenstedt, Jake Archibald
Blast from the past!

I'm trying to enable this again for M65 - this time matching exactly what Firefox does.

sarpv...@gmail.com

unread,
May 6, 2018, 6:32:09 PM5/6/18
to blink-dev
Please remove the chrome 65+ this is making a barrier in a different way

shahidul

amol...@gmail.com

unread,
May 22, 2018, 12:39:31 AM5/22/18
to blink-dev
I have yet to see an actual example or explanation of the type of attack avoided by breaking the 'download' attribute behavior. 

justforthe...@gmail.com

unread,
May 21, 2019, 9:34:54 AM5/21/19
to blink-dev
Same here.

As many users, I still cannot find a real attack and a sensible justification to block the "download" attribute. It seems to me more due to a misunderstanding of some terms or a bad implementation of the code that manages the attribute.

The "download" attribute should be a way to instruct the browser "don't render this file, let me download it". This just prevents the default browser behaviour. Browsers will not render EXE files for example, and they will be downloaded anyway. But sometimes it is desireable to download a JPEG or a PDF instead of rendering in the browser. The browser is not always desired!

Regarding the "user-mediated cross-origin information leakage". So it means that this leakage does not happens when the user uses the "Save As" fucntionality? Or when the browser does not understand the type of the file it is trying to fetch and tries to download it? To be in the safe side then, why not to remove the "save as", or better, the download functionality all together?  It is not me who is speaking, but many users that I have found and have no knowledge about the "Save as" or they find it annoying and tedious to execute.

I believe you are blocking something something inocuous per se. All the points against this attribute I have found so far are not only applicable to the download attribute itself, but to the way the Web is designed. There should be some way to instruct the browser NOT to render the file internally, but to download it. When browsers did not "understand" PDF, it was always downloaded. Now we are forcing users to render the contents in the browser itself. And you are claiming that if you render the content in the browser, there is no possible attack and no possible leakage... I find it very unreal.

So please, can someone give me a real example of attack, that affects the "download" attribute itself (not the Web design, not the way Web links work, not the <a> element) so I can understand why this choice was made? I have been looking for this unsuccessfully for many months already, and I did not find a single valid argument. Yes, there could be attacks using the "download" attribute, but in the same way these attacks could be done with the <a> element. It is like blocking HTTP because "it can transport viruses" while leaving FTP open, if that makes sense. The problem perhaps it is in the transport protocol and the solution in another place.
Reply all
Reply to author
Forward
0 new messages