Conversation
@@ -262,6 +262,10 @@ def initialize(name, resource) | |||
end | |||
|
|||
def fetch | |||
if @url.include?("https://downloads.sourceforge.net") || @url.include?("https://download.gnome") || @url.include?("https://www.apache.org/dyn/") |
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.
Wouldn't https://download.gnome.org
be better than https://download.gnome
here? .com
and .net
aren't used by the GNOME project, though I haven't checked other TLDs.
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 cut off the country code because I was trying to shorten an already lengthy line. Sourceforge
's could also be cut for the same reason.
I don't mind either way though. We can do either, ultimately, if the maintainers like the idea.
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.
No strong preference from here either. One interesting thing is that sourceforge.jp
uses a different setup than the main sourceforge site, so that one is probably best to be handled separately.
This is good as a general disclaimer to avoid false expectations about security, my minor concern is that it will also appear when these redirectors start to switch using secure URLs, thus giving unnecessary worries for an otherwise secure redirect. Ideally redirectors should switch all their mirrors to SSL/TLS at once, but in practice most probably it will be a slow and gradual process (possibly with some plaintext mirrors remaining indefinitely). |
This is largely why I softened the language from "will" and "won't" to "may" and "may not". I favour obeying the majority in this sort of thing; At the moment the majority (almost all, sadly) of the redirects are done to plaintext, so the warning is merited. Once we see the redirects hitting SSL/TLS more than plaintext, I'm happy to murder the warning, or narrow it down more than it is currently. |
Thanks, noted and agreed. |
@@ -262,6 +262,10 @@ def initialize(name, resource) | |||
end | |||
|
|||
def fetch | |||
if @url.include?("https://downloads.sourceforge.net") || @url.include?("https://download.gnome") || @url.include?("https://www.apache.org/dyn/") | |||
ohai "Please note this link may redirect to http and the download may not be protected by SSL/TLS." |
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.
s/link/URL/
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.
Changed 👍
Might be worth trying something where we use |
|
I have some concerns about that being misleading myself. See comment on other thread. On phone atm but will dig out a link when not. Sent from my iPhone
|
I think I may have understood your concern: If the redirection detection and the actual download are two separate curl -sS -f -L 'https://sourceforge.net/projects/upx/files/upx/3.91/upx-3.91-src.tar.bz2' -o 'dl.tar.bz2' -w '%{url_effective}' Effective URL will be on stdout. |
Changing the Feelings on changing any of that @jacknagel @MikeMcQuaid? |
Adding the argument wouldn't be too bad, but at first glance, it looks like changing how curl itself is invoked in order the capture the output would be difficult while maintaining compatibility. One possibility would be something like this: diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index 589147c..d24a06e 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -313,6 +313,7 @@ def downloaded_size
def curl(*args)
args << '--connect-timeout' << '5' unless mirrors.empty?
args << "--user" << meta.fetch(:user) if meta.key?(:user)
+ args << "-w" << "Downloaded from: %{url_effective}\n"
super
end
end but without capturing the output, this would print even in cases where no redirects occur. I dunno. |
Another alternative is to create an option to not allow protocol changes via redirections. This can be implemented by adding [ In case the download would fail this way, Apache now has an implicit https mirror and similar can be implemented for sourceforge/gnome now or in the future. ] |
This makes sense to me. |
I put in a version of this. I don't mind at all if links want to silently upgrade themselves from plaintext to SSL/TLS - Breaking that side of things would send the wrong message. We're only interested in offering a way to block insecure redirects here, IMO. I've added an environmental variable to the mix here, along the lines of your suggestion. I've also changed the download message to mention that variable. The whole run through currently looks like this in practice: Thoughts welcome from everyone. |
If maintainers are happy with the above, I'll probably disable the |
I like these. Only one part I'd argue: protocol upgrades. While convenient and slightly better than full plaintext, these can't IMO be considered secure, because in the initial (or any in-between) plaintext phase the redirection is very easy to spoof and the URL is also visible to any listeners. So, if we're to call the option 'secure downloads only', it'd seem better to exclude them. In such case the right solution is to swap the initial URL in the formula to use SSL/TLS instead. |
To be put it somewhat bluntly, I don't particularly think most users, even those running with the environmental variable, can be consistently relied upon to submit package updates to bump URLs to the correct protocol. My worry there is that we'll end up blocking a lot of things, and instead of users submitting the changes most of the time, they'll just I don't think we can argue this two ways. We say we use |
I agree not to bug users with this. This could rather be something verified in the |
This sounds interesting and we'd review a patch to do this. |
Aye. Agreed. We should do it, but it should be nudged onto formulae authors rather than folks who just want to use Homebrew to deal with package management and not be fussed about the inner workings and such. |
I've updated my prototype shell script with capability to catch this case and show a message accordingly: [sorry for no direct patch - it's my Ruby skills] UPDATE: There is one caveat: If there is a redirector accessible via http-only, which sometimes redirects to |
@vszakats It'd be good if you feel passionate about these things if you can try and work on some Ruby. I'd never written any Ruby before Homebrew and started with formulae and then moved to core code, being a maintainer and now work full-time writing (mostly) Ruby. There are lots of resources and people who will help you. |
Can't argue with that. I'll need to finish some running projects to allocate time for it. What would normally be a 5-60 minutes patch, ATM requires days, including to find out how to create/run a spare working copy of Homebrew where debugging is done. Ruby has lots of ways to achieve the same result, which requires an extra leap to create something presentable. I'm hoping to get there eventually. |
Thanks @vszakats, much appreciated. |
Pushed a change so the message doesn't print if the environmental variable is set. |
👍 |
I'm happy enough with this if everyone else is at this point, but will adjust if there's any further feedback. |
Any other @Homebrew/owners have thoughts? |
Requesting a day to look it over, haven't kept up with the current proposal (sorry). |
I'd like us to print this URL as I think it'll help with debugging and it's better to keep users informed if there's a protocol downgrade. |
@@ -269,6 +269,17 @@ def initialize(name, resource) | |||
|
|||
def fetch | |||
ohai "Downloading #{@url}" | |||
|
|||
url = resolve_url(@url) |
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.
Might want to call this resolved_url
or actual_url
or something to make the below code a bit easier to follow
To me the diff looks pretty much what I had in mind (with a few tweaks). |
Changes pushed in response to comments. More comment welcome 😉 |
@@ -312,6 +323,11 @@ def _fetch | |||
curl @url, "-C", downloaded_size, "-o", temporary_path | |||
end | |||
|
|||
def actual_url(url) | |||
m = Utils.popen_read("curl", "-I", "-L", url).match /^Location: (.+)$/ |
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 won't work. We cannot add -L
. If you test it, you will see why.
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.
Yes that's what I thought to but I did test it, it worked. Have a reproducible example?
Sent from my iPhone
On 16 May 2015, at 17:28, Xu Cheng notifications@github.com wrote:
In Library/Homebrew/download_strategy.rb:
@@ -312,6 +323,11 @@ def _fetch
curl @url, "-C", downloaded_size, "-o", temporary_path
end
- def actual_url(url)
- m = Utils.popen_read("curl", "-I", "-L", url).match /^Location: (.+)$/
This won't work. We cannot add -L. If you test it, you will see why.—
Reply to this email directly or view it on GitHub.
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 slows the GNU formulae fetch
process down very very slightly. That's the only problem I've seen though. I fetch
ed several SF formulae, several known non-redirected formulae, bottles and source packages. What problem are you expecting to run into 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.
I didn't test it on a resource but on my own website.
$ brew pry
==> Interactive Homebrew Shell
Example commands available with: brew pry --examples
[1] brew(main)> def actual_url(url)
[1] brew(main)* m = Utils.popen_read("curl", "-I", "-L", url).match /^Location: (.+)$/
[1] brew(main)* m.nil? ? url : URI.join(url, actual_url(m.captures.first)).to_s
[1] brew(main)* end
=> :actual_url
[2] brew(main)> actual_url "http://www.xuc.me"
URI::InvalidURIError: bad URI(is not URI?): /
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/uri/generic.rb:1100:in `rescue in merge'
[3] brew(main)>
$ curl -I -L http://www.xuc.me
HTTP/1.1 302 Found
Date: Sat, 16 May 2015 17:09:17 GMT
Connection: keep-alive
Set-Cookie: __cfduid=def8c22540ebda317655e556fef3699ed1431796157; expires=Sun, 15-May-16 17:09:17 GMT; path=/; domain=.xuc.me; HttpOnly
Pragma: no-cache
cache-control: no-cache
Location: /
Server: cloudflare-nginx
CF-RAY: 1e78b07e9429198c-HKG
HTTP/1.1 301 Moved Permanently
Date: Sat, 16 May 2015 17:09:18 GMT
Content-Type: text/html
Connection: keep-alive
Set-Cookie: __cfduid=def8c22540ebda317655e556fef3699ed1431796157; expires=Sun, 15-May-16 17:09:17 GMT; path=/; domain=.xuc.me; HttpOnly
Location: http://xuc.me/
Server: cloudflare-nginx
CF-RAY: 1e78b08194a1198c-HKG
HTTP/1.1 301 Moved Permanently
Date: Sat, 16 May 2015 17:09:18 GMT
Connection: keep-alive
Set-Cookie: __cfduid=ddf971c5bcd00711d97cebfc66f78c9221431796158; expires=Sun, 15-May-16 17:09:18 GMT; path=/; domain=.xuc.me; HttpOnly
Location: https://xuc.me/
Server: cloudflare-nginx
CF-RAY: 1e78b084d9a200c4-HKG
HTTP/1.1 200 OK
Server: cloudflare-nginx
Date: Sat, 16 May 2015 17:09:18 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Set-Cookie: __cfduid=dc3f4faf4b1bb38c89b7f6c00ec55dff51431796158; expires=Sun, 15-May-16 17:09:18 GMT; path=/; domain=.xuc.me; HttpOnly
Last-Modified: Mon, 16 Mar 2015 01:33:56 GMT
Access-Control-Allow-Origin: *
Expires: Sat, 16 May 2015 17:19:18 GMT
Cache-Control: max-age=600
CF-RAY: 1e78b0863c6b1944-HKG
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.
For me:
==> Interactive Homebrew Shell
Example commands available with: brew irb --examples
irb(main):001:0> def actual_url(url)
irb(main):002:1> m = Utils.popen_read("curl", "-I", "-L", url).match /^Location: (.+)$/
irb(main):003:1> m.nil? ? url : URI.join(url, actual_url(m.captures.first)).to_s
irb(main):004:1> end
=> nil
irb(main):005:0> actual_url "http://www.xuc.me"
=> "http://www.xuc.me/"
irb(main):006:0>
Tested using both Ruby 2.2.2 via rbenv
and using Ruby 2.2.2 from Homebrew.
@MikeMcQuaid @jacknagel @vszakats Can you run the above as well and see what reproduces for you?
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.
@xu-cheng Can you explain what's incorrect about mine? I tested it and it produced the expected result so I'm confused.
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.
Ah yes, I see the recursion issue.
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.
Yes, the test may create false positive as there aren't many resources with multiple redirects.
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.
Which version am I using here? Your's or Xu's?
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.
Xu's.
I've addressed this issue to GNOME sysadmins through this ticket, https://bugzilla.gnome.org/show_bug.cgi?id=749481 Which would be far more elegant solution, to get redirect only to valid HTTPS mirrors if the original file is accessed through HTTPS (which means, client is already able to verify SSL certificate chain or deliberately ignores it) |
I'd like to help test this so we can get it merged in. Can you suggest some formulae I can try to reproduce the insecure redirect (ideally one that has a single redirect and one that has more than one)? Thanks! |
Sorry for the late comment. But current implementation is still incorrect. In short, you cannot use My version of |
I need to deal with the multi-hop situation still - I'll rebase this and push that change ASAP.
Those are all pretty small formulae that can (always in GNU's case) insecure redirect off the primary url. Any sourceforge formula will have the same issue, but SF downloads seem to be having issues at the moment (Both in browser and via wget/curl). |
@DomT4 the current output looks great! None of them seem to be |
Thanks! GNOME's rejiggle of redirection priority helped a lot on that - Since they bumped the priority of SSL/TLS mirrors I've barely hit a plaintext one. SF is the main redirector:
|
Another |
Thanks folks. Will test again when you've pushed the code changes (and I guess it should be good to merge then?). Shout when that's happened! |
Alright, code updated, manpage updated. @Homebrew/owners @bfontaine - Let's give this a (hopefully) final review and 👍 / 👎 this. |
As an aside, and something I would prefer not to get super hung up on in this PR, Apache formulae are currently excluded from being impacted by the variable. This is explicit in the manpage. I'd like to automatically shunt Apache formulae onto the secure/private Given the vast numbers of Sourceforge (In particular) formulae in the core, and the general benefits of redirection being announced to both us and users, I think this is worth getting in beforehand. |
Why is Apache excluded, just the different download strategy? If it's not a lot of work it'd be good to enable the same for them for consistency but no worries if that's a later PR. I'll review this more in the next few days and merge if it looks good |
This is a part of it, yeah. It doesn't share the same code as the standard Beyond that though there's always a safe assumption that Apache formulae will have a secure mirror available, which we can use automatically if the |
Thanks to all of you folks, great to see this finalized. |
Thanks for the feedback, assistance and patience in getting this done all 🎉. |
Re discussion in #38824.