Insecure Forms: Passwords and Data Sent Over HTTP
Whatever a visitor types into a form travels to your server when they submit it. Over HTTPS that data is encrypted. Over plain HTTP it crosses every network in between, including public Wi-Fi, the visitor’s ISP and any proxy, as readable text that can be recorded or changed.
There are two ways a form ends up unencrypted:
- The page itself is served over HTTP. Even if the form posts to an HTTPS address, an attacker
on the network can change the page before it reaches the visitor, for example rewriting the
form’s
actionor adding a script that copies keystrokes. The visitor has no way to tell. - The form’s
actionpoints to anhttp://URL, even though the page is on HTTPS. The page looks secure, the padlock shows, and the submission still goes out in plain text.
Why browsers warn
Browsers treat both cases as a problem. A password field on an HTTP page is marked “Not secure” in the address bar and next to the field. Chrome also warns before submitting a form from an HTTPS page to an HTTP address. Visitors who see these warnings tend to abandon the form, and password managers may refuse to fill it.
Login, sign-up, checkout, contact and newsletter forms all count. Names, email addresses and messages are personal data, and privacy laws expect them to be protected in transit.
How to fix
1. Serve the whole site over HTTPS. Get a certificate (free from Let’s Encrypt or your host, or through a CDN such as Cloudflare), redirect all HTTP requests to HTTPS, and add HSTS so browsers stop trying HTTP at all. The HTTPS, HTTPS redirect and HSTS guides cover each step.
nginx redirect:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
Apache (.htaccess):
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
2. Fix form actions. Use relative URLs, or absolute HTTPS URLs:
<!-- Before -->
<form method="post" action="http://example.com/subscribe">...</form>
<!-- After -->
<form method="post" action="/subscribe">...</form>
Hard-coded http:// actions usually come from old templates, embedded newsletter or CRM forms
copied years ago, or a site that moved to HTTPS without updating its database.
3. Check third-party forms. If the form posts to a service (a newsletter provider, a form builder, a payment page), get a current embed code from the provider; they all support HTTPS now.
4. WordPress. After switching to HTTPS, update the WordPress Address and Site Address in
Settings → General, and replace old http:// URLs stored in posts and widgets with a
search-and-replace tool (WP-CLI’s wp search-replace 'http://example.com' 'https://example.com'
handles serialised data correctly). Make a database backup first.
How PerfoMetrix checks this
We look at the forms in the HTML we already downloaded. We send no extra requests to your site and never submit a form.
The check fails when:
- the final page URL is HTTP and the page contains a password field; or
- any form’s
actionresolves to anhttp://address.
The report lists the hosts the insecure forms post to. Pages without forms pass. We check only the scanned page; forms on other pages, or forms added by scripts after the page loads, are not seen.
Further reading: MDN: insecure passwords and OWASP: Transport Layer Security Cheat Sheet.