paragonie / csp-builder

Build Content-Security-Policy headers from a JSON file (or build them programmatically)
https://paragonie.com/projects
MIT License
543 stars 40 forks source link

Add a scheme to whitelisted hosts by default if not specified #3

Closed ScottHelme closed 8 years ago

ScottHelme commented 8 years ago

The csp-builder allows you to specify hosts such as "scotthelme.co.uk" which is a valid definition as per the specification.

https://github.com/paragonie/csp-builder/blob/master/src/CSPBuilder.php#L180

In this scenario the browser should allow the scheme that the policy was delivered over to be used for the 3rd party host. This doesn't work as expected in Safari and can cause unexpected blocking behaviour. Specifying "scotthelme.co.uk" as an allowed host in any policy directive would not allow that resource type to be loaded from "https://scotthelme.co.uk". You can view more details on the bug here: https://scotthelme.co.uk/safari-doesnt-like-csp/

If the user doesn't specify a scheme the csp-builder could default to, or have an option to, use the scheme of the current page obtained by parsing the $_SERVER['REQUEST_URI'] or $_SERVER['HTTPS'].

If the policy is served over HTTP then all hosts specified without a scheme would default to HTTP. In this scenario the browser will allow a scheme upgrade to HTTPS.

If the page is served over HTTPS then all hosts specified without a scheme would default to HTTPS. In this scenario the browser will not allow a scheme downgrade to HTTP.

paragonie-scott commented 8 years ago

I don't think you can get the HTTPS information from $_SERVER['REQUEST_URI'] :)

Thanks for the head's up!

ScottHelme commented 8 years ago

Oops, you're right! I think I was thinking of $_SERVER['HTTP_HOST'], I should read the manual more... In any case, $_SERVER['HTTPS'] should do it.

paragonie-scott commented 8 years ago

From one of my other projects:

    /**
     * Is this user currently connected over HTTPS?
     * 
     * @return bool
     */
    protected static function isHTTPSconnection() : bool
    {
        if (!empty($_SERVER['HTTPS'])) {
            return $_SERVER['HTTPS'] !== 'off';
        }
        return false;
    }

Unfortunately, PHP isn't so straighforward here. But I'll get this rolled out soon.

paragonie-scott commented 8 years ago

Can you confirm that the current master branch effectively mitigates these issues? :)