Privacy Evaluation: Password Checker

Screnshot of the logo found in the Chrome Web Store


For years I have been a huge fan of the HaveIBeenPwned project. One of the problems with it though is that in it’s current state, it is hard to work into the workflow of the average user unless they are only using a handful of passwords or use a password manager that integrates with it.

While doing some research on ways to better integrate HaveIBeenPwned, I came across a Chrome Extension developed by David Hunt called “Password Checker”. This extension supposedly uses the HaveIBeenPwned API (with the K-Anonymity privacy model) to check passwords against HaveIBeenPwned as you type them in the browser. This is a good thing, but before I started using it or recommending it, I wanted to verify that sending passwords to HaveIBeenPwned with the K-Anonymity model was all that the extension did. This article demonstrates my findings.

Version information

The version of the extension which was tested was version 1.0, updated on February 28, 2018. The SHA256 for the data contained in the extension’s folder is EA3DEF2BDDB51C918E622FC35CF1E2FB402D26D8C0B97666928FDA9AC0E90AC2

Screenshot of the version information on the Google Web Store

Permissions analysis

When the extension installs, it asks for permissions to read and change all contents of a webpage. This is to be expected with an extension like this, since it needs to be able to monitor data being entered into input fields, and modify the page to alert the user if it detects that the data was in HaveIBeenPwned. Unfortunately, this also means that the browser has pretty much unlimited access to everything you are browsing and sending to websites; but there is no way around that without breaking the functionality of the extension.

"Add Password Checker?
It can:
Read and change all your data on the websites you visit"

Traffic Interception

The first thing to check in an evaluation like this is for obvious network traffic. Back when most traffic on the web was unencrypted, Wireshark was usually enough for this; but since most traffic is encrypted with TLS these days, intercepting meaningful traffic is not quite as simple. Luckily, there is Burpsuite. Burp allows researchers to install a trusted certificate in their browser and use Burp to intercept encrypted traffic by acting as a Man in the Middle (MitM) proxy between the browser and the site. Since the browser trusts the certificate presented by Burpsuite, it sends the requests to Burp as if Burp was the intended server. Burp then forwards those requests to the server. The server responds to Burp which then responds back to the browser. Since it has been in between the entire communication between the browser and the server, all of the data exchanged can be viewed in Burp.

Using Burp, I configured the browser as described above. I installed the extension and navigated to a test page. I then cleared out the extra “noise” in the targets list in Burp (all of which was associated with legitimate operating system and browser processes) so it was easier to see the data sent specifically by the extension. - the domain of the file used to test the extension.
The test login page used

The only data transmitted during this time was to HaveIBeenPwned’s API service. As “advertised”, it only sent the first 5 characters of the SHA1 of the password I tested (“12345678”). I did not see any analytics data being collected when the page was loaded, or over the next few minutes as I stayed on the page.

Screenshot of Burpsuite only having transmissions to
Screenshot showing the SHA1 hash of "12345678".
SHA1 hash of the password I tested

As expected, I received a notification in the browser that the password had been “pwned”.

Screenshot of the "pwned" message

Source code review

Traffic interception is all well and good for a cursory examination; but it’s just an example of what happened in that specific circumstance. How do we know there isn’t hidden functionality that only activates on certain websites or after a certain amount of time? The best way to verify this is with source code review. The source code of the extension is listed at; but how do we know that matches what is in the Google Web Store? Luckily Chrome extensions are just zipped files containing readable source code – which should match what is in the Github repository. To verify that I am looking at exactly what I am receiving, I investigated the source of the extension installed on my computer. I found that in the expected location of “C:\Users\[Username]\AppData\Local\Google\Chrome\User Data\Default\Extensions\dabcphajoohopnpkpniojiebkohgmean\1.0_0”.

Screenshot of the root folder of the source code.

Luckily, it appears that there isn’t a lot of complexity to this browser extension, so reviewing the source was fairly easy. The _metadata folder contained two .json files. These files are used to validate that the source code files have not been modified or corrupted.

Screenshot of the _metadata folder.

The css folder contained a css file (as could be expected). This helps to style the content used in the extension. The css file seemed to primarily contain base64 encoded images.

Screenshot of the content.css file and the css folder.

The icons folder simply contained 4 .png files of the extension’s icon.

The background.js file contained the function to make the API calls and process the data. It was fairly easy to follow regardless of the lack of commenting. It seemed pretty straight forward that the only place that data was getting sent to from within this file was to HaveIBeenPwned.

Screenshot of the source of background.js

The browser-polyfill.min.js is a open source project from Mozilla. The version in use in this extension is version 0.2.1. I downloaded a fresh copy of the minified file of browser-polyfill 0.2.1 from Mozilla, and compared the SHA256 hashes. They matched, meaning the file had not been modified and can be considered known-good. (The resulting hash was DB9EA23C5B619544C56C04FDB450CD88DB7F220021344EDC44C2E5CF95287826)

Screenshot showing SHA256 hashes of browser-polyfill 0.2.1.

The content.js file was a little longer, so it was a little harder to follow without comments; however, no web calls were made directly from the file, and the file dealt with interacting with the browser and sending the data from password fields with values over 8 characters to background.js on the keyup event. Additionally, this file controlled what happened when the user clicked on the messages from the plugin and positioning of the messages.

The manifest.json was a standard manifest file that tells Chrome what the extension is, what permissions it needs, what files should be called when it is being executed, etc.


While the permissions for the extension could be concerning, they are understandable given the functionality of the plugin.

No evidence could be found via traffic interception or source code review that would suggest that the plugin has any hidden functionality and that it has no malicious capabilities.

This extension in its current form is a welcome tool that the average user could find very useful in ensuring that the passwords which they use have never been compromised in any known data breaches contained on HaveIBeenPwned. It is highly recommended for power users and average users alike, along with a password manager for proper password practices.


This analysis is a point in time review, and it is possible that the plugin could be updated at any time with additional functionality. This analysis may not be adequate for future versions/updates; however, it is in-depth for the current version and shows that at least in the current version, it does what it claims, and no more.

About thegeekkid

Leave a Reply

Your email address will not be published. Required fields are marked *