Avoiding and Correcting Mixed Security Messages in HTML

Depending on what browser and what version you use, the dialog box will appear differently.  The message is still the same though: You're viewing a secure page (https://...) and a warning pops up that there is some insecure content mixed in, asking you what to do about it.  It happens on small sites, corporate sites, even banks, social networking and other very large sites that should have the technical know-how not to scare you like that.  (This can be especially scary when you get security messages from your bank's website!)

So what is it?  The security warning sounds like a hacker has modified the page and is trying to either infect your machine or intercept your data on the way to the website you're visiting.  While in some cases this actually may be true, most times it ends up being  just that there is some element of the secure page that is being retrieved from a non-secure method.  This doesn't necessarily mean dangerous, only not encrypted.  When you see this on somebody else's site, the safest bet is to view only the secure data first, and see what the result looks like.  The result can be anything from a missing image, javascript not working, or a very ugly page because the stylesheet didn't load.

If this error appears on your own site, which you know doesn't contain any malicious hacking code, what do you do about it? When a page is delivered over a secure connection (https) the browser expects everything on that page to come from the same secure connection.  This means all images, stylesheets, javascript code and libraries need to come from https as well.  In a large percentage of cases, you'll find a javascript file or library being pulled in from a standard http server. If you reference an external javascript file from another server, using http://servername... that will trigger the security warning.  The same applies for calling images from another server, which is a common technique for distributing the server load by hosting images separate from the main content.  So the way to solve this is to load everything from a secure https connection.  Depending on how your code is written, this can be done either by writing all references with a complete URL such as https://myserver.com/images/foo.jpg or if they are on the same server your page is on, by a relative URL such as /images/foo.jpg.  Once there are no longer any non-secured items in your secure page, the warning should go away.  (Note: This does not apply to outbound URLs - you don't have to worry about changing your <a> tags, so <a href="http://www.google.com">Google</a> is still okay.)

A sneaky trick - Suppose it's possible that the same page can be delivered to your user by secure or insecure servers.  You don't want to slow things down and waste the user's time by delivering images, styles and javascript securely if you don't need to, so how do you use https only when the main page is delivered by https?  Through a little-known but very handy trick... don't include the protocol itself in the URL.  So instead of writing <img src="https://imgserver.myserver.com/images/foo.jpg> you can write it as <img src="//imgserver.myserver.com/images/foo.jpg> and omit the "http" or "https" altogether.  This tells the user's browser to use whichever protocol the current page is using.  I use this technique when I load the jQuery library on a page, so I don't have to worry about using the secure or non-secure links when referencing the externally-hosted library.  

Important note about browser settings - If you search around on your favorite search engine for getting rid of the mixed security mode error, many sites will give you directions on changing your browser settings to enable display of mixed content.  Besides the fact that it only changes the behavior for YOUR browser, not everyone else's, this is the web-surfing equivalent of closing your eyes when somebody points a gun at you.  The potential danger is still there, but you don't see it.  The better solution is to fix the actual issue with your own site so that it doesn't exist in the first place.  Change your mixed-mode settings with extreme caution.. they can hide a real problem from view if there is malicious code on somebody else's site.

Comments (2)

Robert SilverSr. Software Engineer

Okay if the //serverxyz.com/myimage.jpg or  //serverxyz.com/xyz.js   works
what about a   <a href="//serverxyz.com/home.html">home page</a>  ????


I don't have access to a secure server to test it with at the moment, but did some searching and found an article that says it does work (What's the Protocol?) although I suspect there would be few cases where that's necessary.  

If your link is to the same server (taking your example above literally) then you would just need to point to <a href="/home.html">home page</a> and skip the servername.  This would be the most common method, which would use the current protocol.

If you are indeed linking to an external server, and need to maintain the same protocol as your current page, then according to the article I referenced above, it should work as <a href="//someotherserver.com/home.html">home page</a>.

He does bring up some valid warnings in the article, as well... namely that some javascript libraries or content management systems may get confused by a URL without a protocol, and either add it back in or produce unpredictable results.  Also, IE7 and IE8 apparently will load 2 copies of a CSS file if you use this technique, which will not necessarily be harmful, but will increase load times slightly.

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.