github / secure_headers

Manages application of security headers with many safe defaults
MIT License
3.15k stars 251 forks source link

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

Open guiprav opened 7 years ago

guiprav commented 7 years ago

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

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
[...]
oreoshake commented 7 years ago

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 commented 7 years ago

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

guiprav commented 7 years ago

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!

oreoshake commented 7 years ago

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 notifications@github.com 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 .

Malvoz commented 5 years ago

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.

dmolesUC commented 3 years ago

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

moatorres commented 1 year ago

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.

stychu commented 6 months ago

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

Githamza commented 4 months ago

2024 safari 17.4.1 same issue