Password Vault

An offline-first password manager that runs entirely in your browser. No server, no cloud, no tracking — your vault lives on your machine.

Features

  • AES-256-GCM encryption — All credentials encrypted with a key derived from your master password via PBKDF2 (600,000 iterations). The key exists only in memory.
  • Zero network calls — Works from file:// or localhost. No APIs, no analytics, no telemetry.
  • Group management — Organize entries into color-coded groups. Create, rename, delete.
  • Full-text search — Instant search across title, username, URL, and notes.
  • Password generator — One-click random password generation in the entry form (🎲 button). Uses Web Crypto API for cryptographically secure randomness.
  • Copy to clipboard — One-click copy with 15-second auto-clear.
  • JSON import/export — Export your vault as encrypted JSON with selective group filtering. Import with merge or replace mode.
  • Auto-lock — Vault locks automatically on tab switch, visibility change, or 5-minute inactivity timer.
  • Dark theme — Responsive layout that works on desktop and mobile.

Quick Start

npm install
npm run dev        # http://localhost:5173

Production Build

npm run build      # → dist/index.html (single self-contained file)
npm run preview    # test the production build locally

The build produces a single dist/index.html file with all JavaScript, CSS, and assets (including favicon) inlined as data URIs. No external files, no network requests — it works from:

  • file:// protocol (open dist/index.html directly)
  • Any static web server (nginx, Apache, GitHub Pages, etc.)
  • USB stick, email attachment, or any offline medium

The single-file output is handled by vite-plugin-singlefile for JS/CSS inlining, plus a post-build script that inlines the favicon SVG and removes leftover asset files.

Encryption Flow

Master Password ──PBKDF2──→ 256-bit Key ──AES-GCM──→ Encrypted Credential
                  (600k iters)
                      │
                      └── Salt stored in IndexedDB (not encrypted)
  • The encryption key is never persisted — it lives only in JavaScript memory.
  • A test payload (random string) is encrypted on vault creation and stored alongside the salt. On unlock, the entered password is used to derive a key and decrypt the test payload — if decryption succeeds, the password is correct.
  • On tab close or auto-lock, the key is cleared from memory.

Storage Schema (IndexedDB)

Store Fields
entries id, title, username, encryptedPassword (encrypted), url, notes, groupId, tags, createdAt, updatedAt
groups id, name, color, createdAt
meta salt, testEncrypted, testPlaintext, dbVersion

Security Considerations

Threat Mitigation
Key persistence Key stored only in $state, cleared on lock/close
Weak passwords 16-character default with mixed character types
Clipboard leakage Auto-clear after 15 seconds
Tab left open Auto-lock on visibility change (tab switch)
Database tampering Passwords encrypted at rest with AES-256-GCM
Brute force PBKDF2 with 600,000 iterations slows offline attacks

Known limitations

  • No browser fingerprinting or anti-keylogger — This is a local tool, not a hardened security appliance.
  • IndexedDB can be inspected — Only encryptedPassword is encrypted at rest. Titles, usernames, URLs, and notes are stored in plaintext for searchability and are visible if the database is inspected.
  • Test plaintext stored in IndexedDB — The testPlaintext value used for password verification is stored unencrypted in the meta store. An attacker with access to IndexedDB could use it to verify guessed passwords alongside the salt.
  • No automatic backups — Use the JSON export feature to back up your vault regularly.

Development

npm run dev          # Start dev server with HMR
npm run build        # Production build (zero warnings target)
npm run preview      # Preview production build

Stack

  • Svelte 5 — Runes-based reactivity ($state, $derived, $effect), props-based event passing
  • Vite 8 — Build tool and dev server
  • vite-plugin-singlefile — Inlines all JS/CSS into a single HTML file
  • idb — Promise-based IndexedDB wrapper
  • Web Crypto API — Native browser cryptography (no external crypto libraries)
  • Vanilla CSS — Dark theme with CSS custom properties, no preprocessors

License

MIT

Description
No description provided
Readme 1.7 MiB
Languages
JavaScript 52.4%
Svelte 44.9%
CSS 2.5%
HTML 0.2%