Bitwarden × HaveIBeenPwned — local, private, zero-upload password auditing
PS vault-scanner is a Windows desktop GUI that audits an exported Bitwarden vault against the HaveIBeenPwned Pwned Passwords database. Passwords are checked using the k-anonymity range API — only the first 5 characters of a SHA-1 hash ever leave your machine. The full password, and the full hash, never travel anywhere.
Beyond breach detection, the scanner performs a full reuse and similarity analysis across your entire vault using Levenshtein distance and trigram overlap, so passwords like Twitter2024 and Twitter2025! are flagged as dangerously similar even if neither has been breached.
| Breach detection | Checks every login password against the HIBP Pwned Passwords database |
| Reuse detection | Flags identical passwords used across multiple accounts |
| Similarity detection | Catches near-duplicate passwords via Levenshtein distance + trigram overlap |
| Leetspeak normalization | P@ssw0rd and password are treated as the same password |
| k-anonymity | Only a 5-character hash prefix is sent to HIBP — your passwords never leave your machine |
| Rate-limit resilience | Automatic retry with Retry-After header respect (up to 5× for 429s) |
| CSV export | Export the full results table for external reporting |
| Offline-safe scan start | Vault is parsed and validated before any network request is made |
Bitwarden JSON export
│
▼
┌─────────────┐
│ Parse & │ Validates "items" field, rejects files > 50 MB
│ Filter │ Extracts login entries with non-empty passwords
└──────┬──────┘
│
▼
┌─────────────┐
│ Phase 1 │ SHA-1 hash → send first 5 chars to HIBP API
│ HIBP Check │ Match response suffix → breach count
└──────┬──────┘ ▲
│ └── Passwords never sent. Hashes never stored on entries.
▼
┌─────────────┐
│ Phase 2 │ Reuse: exact hash match across entries
│ Analysis │ Similarity: Levenshtein ≤ 25% + trigram overlap ≥ 65%
└──────┬──────┘ (after leetspeak normalization)
│
▼
Results table → Filter → Export CSV
Status definitions:
| Status | Meaning |
|---|---|
| 🔴 BREACHED | Password appears in a known data breach |
| 🟡 REUSED | Same password used on multiple accounts |
| 🟠 SIMILAR | Password is a near-duplicate of another in your vault |
| 🟢 SAFE | Not breached, not reused, not similar |
| ⚫ ERROR | HIBP API unreachable after retries |
- Windows (WPF GUI — Windows only)
- PowerShell 5.1 or later (
powershell.exeorpwsh) - Internet connection for the HIBP API during Phase 1
- A Bitwarden JSON export (unencrypted — see below)
The script auto-detects MTA threading environments (e.g. PowerShell 7 /
pwsh) and relaunches itself viapowershell.exe -STAautomatically. No manual flags needed.
In the Bitwarden desktop app or web vault:
Settings → Export Vault → Format: JSON (unencrypted)
Warning
The exported file contains your passwords in plain text. Store it securely and delete it after scanning.
# Double-click HIBP_Scanner.ps1, or run from any PowerShell prompt:
powershell.exe -ExecutionPolicy RemoteSigned -File .\HIBP_Scanner.ps1If you get an execution policy error, run once from an elevated prompt:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned- Click Browse and select your exported
.jsonfile - Click Scan Vault
- Wait for Phase 1 (HIBP) and Phase 2 (reuse/similarity) to complete
- Use the filter tabs or metric cards to drill into results
- Optionally click Export CSV to save a report
| Guarantee | Detail |
|---|---|
| Passwords never transmitted | Only a 5-char SHA-1 prefix is sent to api.pwnedpasswords.com |
| Hashes never stored on entries | SHA-1 hashes exist only in a temporary index, cleared immediately after Phase 2 |
| Vault path not retained | The file path is nulled out as soon as the scan runspace starts |
| TLS 1.2 minimum | Pinned at startup; TLS 1.3 enabled where available |
| 50 MB file size cap | Prevents runspace OOM on crafted input files |
| No telemetry | The script makes no outbound requests other than HIBP range lookups |
The HIBP range API returns ~800 hash suffixes per prefix — your specific password cannot be identified from the request even if the connection were intercepted.
Tests are written with Pester. Install it if needed:
Install-Module Pester -Force -Scope CurrentUserThen run:
Invoke-Pester .\HIBP_Scanner.Tests.ps1 -Output DetailedThe test suite covers SHA-1 hashing, Levenshtein distance, leetspeak normalization, trigram overlap, similarity detection, the status map, and script requirements (TLS availability, WPF loadability, STA guard presence).
HaveIbeenPwned Scanner/
├── HIBP_Scanner.ps1 # Main script — WPF GUI + scan engine
└── HIBP_Scanner.Tests.ps1 # Pester unit + integration tests
Pull requests are welcome. Please ensure Invoke-Pester passes before submitting.
This project is licensed under the GNU General Public License v3.0 — see the LICENSE file for details.
You are free to use, modify, and distribute this software under the terms of the GPL v3. Any derivative works must also be distributed under the same license.
