What is meta? ×
Meta Stack Exchange is where users like you discuss bugs, features, and support issues that affect the software powering all 134 Stack Exchange communities.

Stack Overflow has HTTPS in some places! However, this breaks most existing image links. Could those be made protocol-relative, or react to the requesting protocol, or just always use HTTPS?

The same applies to .sponsor-tag-img.

share|improve this question
Sure, you could do this for Imgur links, but not all links. We can't guarantee other external image servers will actually support SSL, and automatically changing it could simply break the link. In the grand scheme of things, any time you allow users to embed external resources into a page, you simply cannot guarantee that the page will ever be fully SSL compliant. –  animuson Feb 15 '14 at 19:16
@animuson: Sure, and I’ll use the rehost button when I see those images, or just not look at them. This question is specifically about the ones we know have support, i.e. imgur. If not any user content at all, then at least the parts of the site itself (like .sponsor-img-tag). –  minitech Feb 15 '14 at 19:19
I don't think always using HTTPS would be a good choice, even if it only applied to imgur links. This would increase the latency of the image download, which could have a significant impact on mobile clients, and often have no benefit. Protocol-relative on a web-page would be the way to go. –  Aaron Brager Feb 15 '14 at 19:33
Also, if the same image URL information is used to generate payloads for the Stack Exchange iOS/Android apps, the image should almost always be HTTP since mixed protocols isn't an issue there. –  Aaron Brager Feb 15 '14 at 19:34
@AaronBrager: Mixed protocols aren’t disallowed for fun. It’s a security (well, privacy) problem. Yes, even globally-accessible images without cookies. –  minitech Feb 15 '14 at 20:05
Right, but on web non-private images are commonly sent via HTTPS to avoid mixed protocol errors. My point was simply: if the images are not private, it's wasteful to use HTTPS to transmit them. –  Aaron Brager Feb 15 '14 at 20:14
Nick does discuss this in his blog post on bringing SE to HTTPS‌​: Inline Images: we can’t include insecure content on the page…so that means turning our images to SSL when i.stack.imgur.com is ready. For other domains images are embedded from we have to turn them into links, or solve via another approach. –  hichris123 Feb 15 '14 at 22:38
@hichris123: Yes, i.stack.imgur.com has supported HTTPS for a while. –  minitech Feb 18 '14 at 20:39
Investigating a different SSL issue, I noticed that gravatars cause mixed content messages to the console as well. Since Gravatar does support HTTPS, fixing both issues at the same time should be feasible. –  MvG Mar 24 '14 at 7:20
If rewriting image URLs in posts is too much work, could we at least get this fixed for user avatars uploaded to i.stack.imgur.com? Gravatar images already seem to be using protocol-relative URLs, so it seems like at least some similar code must already be in place. –  Ilmari Karonen Jul 23 '14 at 19:47

1 Answer 1

The just released Stack Overflow Unofficial Patch v1.14 includes a client-side work-around for this issue.

Ideally, such a work-around would intercept any requests for image files over HTTP and rewrite them to use HTTPS. However, while this is possible for a browser extension like HTTPS Everywhere, I'm not aware of any cross-browser way to do it with a simple user script like SOUP.

Instead, the way this work-around works is by detecting images that:

  1. have failed to load,
  2. have a http: URL on a page loaded over https:, and
  3. are on a domain known to support HTTPS simply by changing the protocol in the URL.

Notably, condition #1 means that this work-around only applies if your browser is configured to block insecure images on secure pages. For Firefox, this setting is available on the about:config page as security.mixed_content.block_display_content. I'm not currently aware of any way to change this setting for other browsers.

This also means that you'll still get mixed-content errors in your browser error log; the work-around just reloads the images over HTTPS after they've failed to load over insecure HTTP.

Also, while SOUP does try to re-run the work-around code whenever new content is injected via AJAX or otherwise modified, it's possible that there may be some remaining cases where dynamically loaded images are not fixed properly. If you find any, please let me know.

The domains for which the work-around is enabled currently include:

  • imgur.com (including stack.imgur.com), used for user-uploaded images using the SE editor's upload tool, as well as for user avatars uploaded via SE;

  • gravatar.com, used for global user avatars (actually, gravatar images seem to be already loaded over HTTPS anyway, but I've included it just in case);

  • facebook.com, used for avatars for users logging in via Facebook;

  • wikimedia.org (including upload.wikimedia.org), a popular source of freely licensed images;

  • sstatic.net, used for some SE interface graphics, such as site icons (mostly loaded over HTTPS already, but IIRC I found some broken ones when I tested this); and

  • stackexchange.com and all other Stack Exchange sites (stackoverflow.com, superuser.com, serverfault.com, stackapps.com, askubuntu.com, mathoverflow.net), used e.g. for user flair images.

Some notable examples of domains to which the workaround is not applied include chart.apis.google.com (Google Charts, does not seem to support HTTPS) and imageshack.us (could be supported, but would require more complex URL mangling than just changing the protocol).

Just in case you're curious, here's the whole code, as included in SOUP v1.20.0:

if ( 'https:' != location.protocol ) return;
var urlRegex = /^http:\/\/(([a-z0-9\-]+\.)*((imgur|gravatar|facebook)\.com|wikimedia\.org|sstatic\.net|(stack(exchange|overflow|apps)|superuser|serverfault|askubuntu)\.com|mathoverflow\.net))\//i;
var fixImages = function (target) {
    $(target).find('img[src^="http://"]').each( function () {
        if ( ! urlRegex.test( this.src ) ) return;
        if ( ! this.complete || this.naturalWidth > 0 ) return;
        var newUrl = this.src.replace( urlRegex, 'https://$1/' );
        SOUP.log( 'soup mse221304 fixing img ' + this.src + ' -> ' + newUrl );
        this.src = newUrl;
    } );
SOUP.addContentFilter( fixImages, 'HTTPS image fix' );
$(document).on( 'mouseenter', '#user-menu', function () {
    SOUP.try( 'HTTPS image fix', fixImages, [this] );
} );
share|improve this answer
Why don’t you just make it replace all http: images, errored or not? (I do have everything configured to block passive mixed content, so it shouldn’t make any difference, but might prevent warnings.) –  minitech May 11 '14 at 0:34
@minitech: Because there's not much point -- the browser has already started to load the image before the script has a chance to kick in, so the insecure request has already been made (and may well have already completed). At that point, if the request wasn't blocked, reloading the image over HTTPS would be just closing the stable door after the horse has bolted. It would also waste bandwidth for users with insecure image loading enabled, since every image would be requested twice, first over HTTP and then over HTTPS. –  Ilmari Karonen May 11 '14 at 0:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .