Privacy Browser Security and Privacy Canary

August 2016 Security and Privacy Canary


During the previous year, Stoutner has received 0 requests from governments or organizations to insert backdoors into Privacy Browser.

During the previous year, Stoutner has inserted 0 backdoors into Privacy Browser.


During the previous year, Stoutner has received 0 requests from governments or organizations to weaken the privacy of Privacy Browser.

During the previous year, Stoutner has made 0 changes to weaken the privacy of Privacy Browser.

Legal Requests for Information

During the previous year, Stoutner has receive 0 legal requests for information from government law enforcement organizations. These requests sought information for a total of 0 individuals.

During the previous year, Stoutner provided information in response to 0 legal requests for information from government law enforcement organizations. These responses included information for a total of 0 individuals.

The types of information that Stoutner possesses and can disclose to legal requests from government law enforcement organizations are described in the privacy policy.

Privacy Browser

The “X-Requested-With” Header

As mentioned is several places on this website and in the app, there are some negative implications of using Android’s WebView to render web pages in Privacy Browser. The purpose of this post is to describe one of these downsides, explain the mitigations that are currently being taken, and lay out thoughts for a more permanent solution down the road.

The Background

When any app uses Android’s WebView to request a web page, WebView attaches an extra header, named “X-Requested-With”, with the app ID. “X-Requested-With” was designed to be used as a flag to mark AJAX (Asynchronous JavaScript and XML) requests. In that sense, WebView’s use of the field for a different purpose is an abuse of the standard and can cause problems for some web pages.

The Problem

One of the web tracking technologies that Privacy Browser is designed to mitigate is browser fingerprinting. Any piece of information the browser sends a web server that makes it stick out from the crowd increases the ability of the web server to uniquely fingerprint the browser. Including the app ID in the header, especially as long as Privacy Browser has a small market share, increases the chance that the total information sent to the server is unique.

For the Standard version of Privacy Browser the app ID is “com.stoutner.privacybrowser.standard”; the Free version is “com.stoutner.privacybrowser.standard”. The following is a log from that shows what information Privacy Browser <= 1.8 transmits to a web server (note that the User Agent has been changed from the default to “PrivacyBrowser/1.0”).

GET / HTTP/1.1||Connection:keep-alive|Cache-Control:max-age=0|Upgrade-Insecure-Requests:1|User-Agent:PrivacyBrowser/1.0|Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|Accept-Encoding:gzip, deflate|Accept-Language:en-US|X-Requested-With:com.stoutner.privacybrowser.standard

The Workaround

Google doesn’t want to make it easy to get rid of the “X-Requested-With” header. However, there is a mechanism for replacing header information. This doesn’t allow a program to stop sending the “X-Requested-With” header, but it does allow a program to replace the app ID with a null value. Beginning with Privacy Browser 1.9, the following information will be sent in the headers:

GET / HTTP/1.1||Connection:keep-alive|Upgrade-Insecure-Requests:1|User-Agent:PrivacyBrowser/1.0|x-requested-with:|Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|Accept-Encoding:gzip, deflate|Accept-Language:en-US

The Problems with the Workaround

The first problem with this workaround is that sending “X-Requested-With:” is not the same as not sending it at all. There are only going to be a few browsers that send “X-Requested-With:” as a header, so for fingerprinting purposes this workaround is only slightly better than including the app ID.

The second problem is that the technique for overwriting WebView’s headers only works on the initial request to a website. Any dependent requests for resources (like images, CSS files, JavaScript files, etc.) use the default headers. So even in Privacy Browser >= 1.9, the log of a request for a resource will be as follows:

GET /wp-content/themes/twentysixteen/style.css?ver=4.5.3 HTTP/1.1||Connection:keep-alive|Cache-Control:max-age=0|User-Agent:PrivacyBrowser/1.0|Accept:text/css,*/*;q=0.1|Referer:https%3a//|Accept-Encoding:gzip, deflate|Accept-Language:en-US|X-Requested-With:com.stoutner.privacybrowser.standard|If-None-Match:"10d4b-535f10e3fb580-gzip"|If-Modified-Since:Thu, 23 Jun 2016 12%3a18%3a46 GMT

This is a problem for every browser that uses Android’s WebView. For example, Lightning 4.3.3 behaves the same way as Privacy Browser >= 1.9: initial web requests include “X-Requested-With:” and resource requests include “X-Requested-With:acr.browser.lightning”.

The Long-Term Solution

There is a provision in WebView to bypass the default web loading functions by manually acquiring the information using HttpURLConnection and feeding it into WebView. This would allow the complete removal of the “X-Requested-With” header. However, making sure that all possible types of HTTP communication are handled correctly would be complex and the initial implementation would likely result in buggy behavior on some websites.

Another solution is to stop using Android’s WebView and embed a customized WebView in Privacy Browser. This would also allow for the complete removal of the “X-Requested-With” header, but would be a time consuming commitment to maintaining the custom WebView (both from a security and bug perspective).

Long term, it is likely that using a custom WebView will be the best solution for Privacy Browser. The plan is to implement all the privacy functions that are compatible with Android’s WebView (pick the low hanging fruit) and then do a detailed analysis of the best way to move beyond that point.

Privacy Browser

Privacy Browser 1.8

I have decided that I am going to make a regular habit of posting when a new version of Privacy Browser is released, detailing what users can expect from the new version and what I am working on for the subsequent release.

The main feature in Privacy Browser 1.8 is a bookmark implementation. This is a fairly robust implementation that allows for the creation of bookmarks, folders, and subfolders, reordering of bookmarks, moving of bookmarks between folders, and editing of bookmarks and folders.

For Privacy Browser 1.9, I intend to implement SSL certificate controls, as well as WebView font size controls, both of which are features that have been requested by users.

I have also received a request to hold off on implementing features that require the addition of dangerous permissions. For users on Android Marshmallow or newer (version >= 6.0, API >= 23), dangerous permissions are not an issue because they can choose to only enable those that are required for the features they want to use. But for those on older versions of Android, they do not have the option to disable individual permissions. Several planned feature will require the use of dangerous permissions, particularly READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE. The concern is that websites will be able to take advantage of 0-day flaws in WebView to abuse the user’s phone through the use of these permissions.

My thought is to implement all the planned features that don’t require dangerous permissions before implementing those that do. Hopefully, by that time more people will have devices that run at least Android 6.0. Privacy Browser 1.8 runs on Android KitKat (4.4, API 19) and newer. According to the July 2016 Android Dashboard, 78.5% of devices that access the Google Play Store are running Android 4.4 or newer. Of the group that can install Privacy Browser, only 16.9% (13.3 / 78.5) are running Android 6.0. I would like to see that number closer to 50% before implementing features with dangerous permissions.

Android Dashboard

Early adopters of Privacy Browser tend to be a more technologically savvy group and have more advanced hardware than the average Android user. The Google Play Store provides summary installation information that shows that 41.67% of current Privacy Browser installations and 33.33% of Privacy Browser Free installations are on devices running Android 6.0. These numbers only represent installations throught the Google Play Store, which doesn’t account for the few installations through the Amazon Marketplace or what I am assuming are the fairly large number of installations through F-Droid.

Privacy Browser

Privacy Browser 1.7

With the release of Privacy Browser 1.7, I felt it would be valuable to write a post explaining the motivation behind the design decisions and what is coming next.

Privacy Browser 1.7 marks the single largest number of changed lines in the code since version 1.0 was released. It began as a need to create a more thorough About section to accommodate attributions for contributions. This expanded into a Guide that explains the basic principles and functionality of Privacy Browser.

The minimum API was increased to 19 (Android KitKat 4.4 or higher) with this release due to security concerns with the embedded WebView in older versions of Android. I imagine that the majority of the users of Privacy Browser already use devices with API >= 19. F-Droid, where I would imagine the majority of users acquire Privacy Browser, does not collect statistics from users. Google Play’s statistics show that nobody who has downloaded Privacy Browser or Privacy Browser Free is running a device with API <= 18.

Privacy Browser 1.8 will likely include bookmarks, which is my wife’s single most anticipated feature. There will probably also be a few other features that are easy to implement as well.