secure_headers icon indicating copy to clipboard operation
secure_headers copied to clipboard

Don't upgrade insecure requests when the page is served over HTTP

Open guiprav opened this issue 8 years ago • 10 comments

I want to set upgrade_insecure_requests only if the page is requested over HTTPS, because I don't use HTTPS when developing on localhost (i.e. when developing, I browse http://localhost, not https://localhost).

Right now if I set upgrade_insecure_requests, I can't develop locally since all internal resource requests are upgraded, and since my local server doesn't support HTTPS, they fail.

I think this should be a fairly typical scenario. Would this be considered a bug, or is there a work-around for it?

Relevant software versions

  • rack 1.6
  • secure_headers 3.6.7

Expected outcome

  1. I configure CSP to upgrade_insecure_requests.
  2. I browse http://localhost while developing.
  3. upgrade_insecure_requests header shouldn't be set, since it's pointless as the webpage itself is being insecurely served.

Actual outcome

  1. upgrade_insecure_requests header is set and all internal resources are broken.

Config

  SecureHeaders::Configuration.default do |config|
    config.cookies = {
      secure: true,
      httponly: true,
      samesite: {
        lax: true
      }
    }
    # Add "; preload" and submit the site to hstspreload.org for best protection.
    config.hsts = "max-age=#{20.years.to_i}; includeSubdomains"
    config.x_frame_options = "DENY"
    config.x_content_type_options = "nosniff"
    config.x_xss_protection = "1; mode=block"
    config.x_download_options = "noopen"
    config.x_permitted_cross_domain_policies = "none"
    config.referrer_policy = "same-origin"
    config.clear_site_data = [
      "cache",
      "cookies",
      "storage",
      "executionContexts"
    ]
    config.csp = {
      # "meta" values. these will shaped the header, but the values are not included in the header.
      # report_only: true,      # default: false [DEPRECATED from 3.5.0: instead, configure csp_report_only]
      preserve_schemes: true, # default: false. Schemes are removed from host sources to save bytes and discourage mixed content.

      # directive values: these values will directly translate into source directives
      default_src: %w('self'),
      base_uri: %w('self'),
      #block_all_mixed_content: true, # see http://www.w3.org/TR/mixed-content/
      child_src: %w('self'), # if child-src isn't supported, the value for frame-src will be set.
      connect_src: %w(),
      font_src: %w('self'),
      form_action: %w('self'),
      frame_ancestors: %w('none'),
      img_src: %w('self' *),
      manifest_src: %w('self'),
      media_src: %w('self'),
      object_src: %w('self'),
      plugin_types: %w(),
      script_src: %w('self' 'unsafe-inline' maps.googleapis.com),
      style_src: %w('self' 'unsafe-inline'),
      upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
    }
  end

Generated headers

[...]
Content-Security-Policy:default-src 'self'; base-uri 'self'; child-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src *; manifest-src 'self'; media-src 'self'; object-src 'self'; script-src 'self' 'unsafe-inline' maps.googleapis.com; style-src 'self' 'unsafe-inline'; upgrade-insecure-requests
[...]

guiprav avatar Jul 28 '17 04:07 guiprav

So upgrade-insecure-requests "works" on requests that themselves are not secure? I wasn't aware of that but I'm happy that it isn't the other way around.

If that is intended behavior per the spec, we should still apply the header to all requests but provide an OPT_OUT option to skip application for non-https requests.

oreoshake avatar Jul 28 '17 04:07 oreoshake

I'm marking this as a bug, so a fix for this will get ported to 4.x and 3.x

oreoshake avatar Jul 28 '17 04:07 oreoshake

Yeah, it could be a Chromium (56.0) bug, or a weird spec, or there's an odd reason this should work like this. In any case, a workaround would be greatly appreciated, so thanks!

guiprav avatar Jul 28 '17 05:07 guiprav

I suspect this "more secure by default" behavior was intentional, as is the attitude towards most w3c webappsec standards. We should definitely support the opt out behavior either way. On Thu, Jul 27, 2017 at 19:02 Guilherme Prá Vieira [email protected] wrote:

Yeah, it could be a Chromium bug, or a weird spec, or there's an odd reason this should work like this. In any case, a workaround would be greatly appreciated, so thanks!

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/twitter/secureheaders/issues/348#issuecomment-318560376, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbYBF6Xdp1ytCFjJZnwORN7Vhi7IAP9ks5sSWtcgaJpZM4OmHu7 .

oreoshake avatar Jul 28 '17 05:07 oreoshake

I don't have access to test this atm but I'm pretty sure Chrome no longer upgrades requests on localhost. I also filed https://bugzilla.mozilla.org/show_bug.cgi?id=1535919 and they confirmed Firefox shouldn't upgrade on localhost.

Malvoz avatar Mar 25 '19 07:03 Malvoz

Safari 14.0 (15610.1.28.1.9, 15610) still does try to upgrade localhost requests, FWIW. 😕

dmolesUC avatar Oct 23 '20 16:10 dmolesUC

I guess upgrade_secure_headers "working" on non https requests became the default behavior in localhost? Just so I understand better, this issue is from 2017 and I'm still experiencing it as of December 2022.

moatorres avatar Dec 12 '22 15:12 moatorres

2024 Safari Version 16.6 just found out I also experience this issue.

stychu avatar Mar 15 '24 11:03 stychu