Chrome complaining about unsecure form when redirecting after HTTP POST

Hi,

Since the installation my CakePHP 3.8.13 site makes Chrome (87.0.4280.88) complaining about a unsecure form submit when I redirect after a HTTP POST.

The error is found in this blog post:

The only thing that I do is executing the generated code from caked controllers and views.
When I click on the “continue” button everything is fine, when I don’t do a thing and continue to the redirect url manually everything is fine also…

I’ve tripple checked the included .js, .css and images they are all loaded over SSL. Chrome isn’t complaining about a thing in the console view.

Does anyone has an idea why this error is happening? This one is driving me crazy, especially since FireFox, Safari, Edge and Brave are doing what I expect… Executing the redirect.

A piece of code that throws the message in Chrome:

public function add()
{
    $route = $this->Routes->newEntity();
    $routeOptions = $this->routeOptions;

    if ($this->request->is('post')) {
        $route = $this->Routes->patchEntity($route, $this->request->getData());
        if ($this->Routes->save($route)) {
            return $this->redirect(['action' => 'index']);
        }
    }
    $this->set(compact('route', 'routeOptions'));
}

I’m also experiencing this with CakePHP 2.10.x.

Does anyone has an idea what is going one? Can’t find anything on Google :frowning:
Weird thing… when I only display HTML and the form (no css/js) the same thing happens…

Thanks for the input!

Hi jicho, we are running into the same issue. There are some comments from the Chromium developers here: https://bugs.chromium.org/p/chromium/issues/detail?id=1158169#c49

They write:

This warning is expected when a form submission is at some point going over an http:// URL, this includes if the http:// URL redirects to https, since the form is initially submitted to an http URL, to fix it in those cases you have to ensure the entire redirect chain for the form submission is https://, any http step will cause the warning to trigger

So if we can force CakePHP to always use HTTPS, Chrome will stop complaining. It doesn’t matter if there is an Apache or something else rule that redirects HTTP to HTTPS, it just sees HTTP and throws the warning.

Perhaps this piece of code might help from a Stackoverflow question " How to force https in CakePHP without redirect from http?" we’ll try it on our end. https://stackoverflow.com/a/35697014

@mgancarzdsi thanks! I will try this as soon as I can, will take a couple of days.
Will post my results.

As it looks like the proxy is causing the trouble, never thought about that.

FYI the Chromium team has now rolled the change back. See for more detail: https://bugs.chromium.org/p/chromium/issues/detail?id=1158169#c147

They also wrote:

We are planning to re-enable the warnings in Chrome 88 (tentatively going to stable on January 19, 2021), but warning only on forms that directly submit to http://, or that redirect to http:// with the form data preserved through the redirect, so it won’t trigger for the cases mentioned in this bug where the http:// hop didn’t carry the form data.

@mgancarzdsi thanks for the update!

I’ve tried the stackoverflow solution, but it does not seem to work at my side (or maybe I’m placing the code at the wrong place in de /webroot/index.php

After reading the post I see what is happening on my side. There is a proxy that handles the SSL part for the “outside”, but the internal traffic is non-SSL. So CakePHP is assuming a header with http://example.com/next/location is needed after a form post.

Seeing that it makes me wondering why CakePHP is returning a location with domain and not only “/next/location”?

But besides that… Is there an official way to force CakePHP (2.10.x, 3.8.x and 4.1.x) to react with a https url from code? The example on Stackoverflow is only the redirect part, not rewriting the response location.

For now I’ve managed to “fix” it in 3.x and 4.1 by adding the following to the config file:

return [
‘App’ => [
‘fullBaseUrl’ => $host
],

In combination with:

if(!empty(_SERVER['https']) || (!empty( _SERVER[‘HTTP_X_FORWARDED_PROTO’]) && $_SERVER[‘HTTP_X_FORWARDED_PROTO’] == ‘https’)) {
host = 'https://' . _SERVER[‘HTTP_HOST’];
}else{
host = 'http://' . _SERVER[‘HTTP_HOST’];
}

It does the trick, but I’m not completely happy about it. Something like “forceSSL” in the config, or who knows where sounds like a better idea.

For now I’m happy :slight_smile: and I’ve learned about the fullBaseUrl. So I’ve learned a lot today :smiley:

Thanks again for the update.