Local Dockerized tool to bulk-manage passwords saved in Microsoft Edge - metadata only, no vault
1.4K
A local, containerized admin tool for bulk-managing the passwords Microsoft Edge already has saved for your Windows user. It lets you search, filter, categorize, multi-select and bulk-delete saved logins especially useful for wiping out large groups of entries by site, category (e.g. adult sites), duplicates, or an uploaded domain list.
This is not a password manager. It creates no vault, no cloud sync, and no separate password store. It operates directly on Edge's own local
Login Datadatabase and only ever reads/deletes metadata rows. It never decrypts, reveals, or exports passwords.
User Data folder, across Stable/Beta/Dev, and every login database within each profile (see Multiple login stores below).adult). Ships with a starter list and auto-loads any list you add.Edge stores each saved login in a Chromium SQLite database named Login Data (table logins). Two very different kinds of data live there:
| Data | Encryption | Used by this tool |
|---|---|---|
origin_url, signon_realm, username_value, date_created, date_last_used, times_used | plaintext | yes yes list, filter, delete |
password_value | DPAPI + app-bound encryption (ABE) | no never touched |
Because passwords are protected by DPAPI and app-bound encryption (tied to your Windows user and Edge's own process), decryption is not possible from inside a Docker container and this tool deliberately does not attempt it. Your entire use case (searching and bulk-deleting by metadata) needs none of that, since all the metadata is plaintext.
The tool operates on a copy of the DB for listing (so it can read even while Edge is open) and on the live DB only for deletes/restores (which require Edge to be closed).
A single Edge profile can contain several login databases, and recent Edge builds do not always use the file named Login Data:
| File | What it is |
|---|---|
Login Data | Legacy/local store. On some installs this is stale. |
Login Data New | The active store on recent Edge builds where newly saved logins actually go. |
Login Data For Account / For Account New | Passwords tied to the signed-in Microsoft account (sync). |
If you only read Login Data, you can miss entries that Edge is really using (and deleting from a stale file has no visible effect). This tool therefore:
*Backup* and journal/WAL/SHM sidecars);The logins schema varies across Chromium versions. On load the tool runs PRAGMA table_info(logins) and:
date_last_used, times_used, or blacklisted_by_user are missing);id column when present (modern Chromium), otherwise by the legacy composite key (origin_url, username_element, username_value, password_element, signon_realm);EdgePassManager/
EdgePasswordBulkManager.sln
Dockerfile
compose.yaml
.env.example
README.md
CHANGELOG.md
docs/
RECOVERY.md
tests/EdgePasswordBulkManager.Tests/
src/EdgePasswordBulkManager/
Program.cs
appsettings.json
Models/ EdgeProfile, LoginEntry, AppOptions, Results
Helpers/ ChromiumTime, DomainHelper, DomainListParser
Services/ ProfileDiscoveryService, LoginDatabaseReader, DeleteService,
BackupExportService, RestoreService, CategoryService,
ListRefreshService, AuditLog
State/ PasswordManagerState (MVVM view-model)
Components/ App, Routes, Layout, Pages/Home.razor
adult-lists/ bundled starter blocklist
cp .env.example .env
Edit .env and set EDGE_USER_DATA to your Edge User Data folder, e.g.
EDGE_USER_DATA=C:\Users\<you>\AppData\Local\Microsoft\Edge\User Data
BIND_ADDRESS=127.0.0.1
HOST_PORT=8088
READ_ONLY=true
EDGE_MOUNT_MODE=ro
The defaults are a loopback-only, read-only preview. To enable backup, delete and restore operations, explicitly set both:
READ_ONLY=false
EDGE_MOUNT_MODE=rw
The application does not include LAN authentication. Keep BIND_ADDRESS=127.0.0.1 unless a trusted firewall or authenticated reverse proxy protects the port. To deliberately publish it on all interfaces, set BIND_ADDRESS=0.0.0.0.
docker compose up --build -d
Open http://localhost:8088.
Pull the prebuilt image instead of building:
docker pull mfrankovic/edge-password-manager:latest
docker compose logs -f # logs
docker compose down # stop
docker compose up --build -d # rebuild after changes
docker compose ps # includes container health status
Open Application updates in the sidebar. The app shows its installed version and provides a manual Check for updates button. Automatic checks are disabled until you opt in; that preference is stored only in the current browser.
The checker reads the latest stable release metadata from GitHub. It does not download an image, access Docker, or run commands. When an update is available, it displays the release notes and these copyable commands for you to run from the folder containing compose.yaml:
docker compose pull edge-pass-manager
docker compose up -d --no-deps edge-pass-manager
Verify the updated container with:
docker compose ps
docker compose logs --tail 50 edge-pass-manager
Stable releases use version tags such as 1.1.0 and update the latest image tag. Builds from main publish under edge and do not become customer updates.
Persisted host folders (created next to compose.yaml):
data/backups DB backups taken before deletes/restoresdata/exports CSV metadata exportsdata/lists downloaded + uploaded blocklistsdata/logs audit logThe container runs as the non-root .NET app account (UID 1654). Docker Desktop handles Windows bind-mount access. On Linux, create and restrict the persisted directories before startup:
mkdir -p data/{backups,exports,logs,lists}
chown -R 1654:1654 data
chmod -R u=rwX,go= data
cd src/EdgePasswordBulkManager
dotnet run
Development config reads Edge from %LOCALAPPDATA%\Microsoft\Edge\User Data and writes artifacts under ./data.
Edge database writes remain disabled by default; override EdgePassManager__ReadOnlyMode=false only for intentional local write testing.
A typical "clean out a category of saved logins" session:
msedge.exe processes. (Listing/filtering works even while Edge is open it reads a copy.)Login Data New). Tick All stores (aggregate) to work across every store at once.adult), or Duplicates only.DELETE <count>). A timestamped DB backup is taken automatically first, and the delete runs in a single transaction.Tips:
READ_ONLY=true in .env) for a safe look-but-don't-touch deployment.logins columns and a live audit trail.<category>__<anything>.txt (e.g. adult__mylist.txt). Files without __ fall into the default category (adult).0.0.0.0 example.com), plain domains (example.com), #/! comments. Subdomains match a listed parent domain automatically.EdgePassManager:Categories in appsettings.json. The default includes the Block List Project "porn" list, refreshed every 24h.Add another category by editing appsettings.json:
"Categories": [
{ "Name": "adult", "Urls": ["https://raw.githubusercontent.com/blocklistproject/Lists/master/porn.txt"] },
{ "Name": "gambling", "Urls": ["https://raw.githubusercontent.com/blocklistproject/Lists/master/gambling.txt"] }
]
PRAGMA integrity_check; deletes run inside a transaction and roll back on error.ReadOnlyMode and the read-only Edge bind mount are enabled by default for a look-but-don't-touch deployment.See Backup and recovery for the normal and emergency restore procedures.
msedge.exe processes)..NET 8 Blazor Server (interactive) Microsoft.Data.Sqlite Docker (Linux container). No third-party vault logic, no browser extension, no cloud services.
The regression suite uses temporary SQLite databases to cover modern and legacy deletion keys, dry safety controls, transaction rollback, WAL snapshots, unique backups, restore integrity, domain parsing, list-size enforcement and concurrent refresh protection.
dotnet test EdgePasswordBulkManager.sln -c Release
dotnet list EdgePasswordBulkManager.sln package --vulnerable --include-transitive
Content type
Image
Digest
sha256:3527d2648…
Size
122.3 MB
Last updated
2 months ago
docker pull mfrankovic/edge-password-manager