All notable changes to Keyper will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Added published Windows installer download for the current release (
KeyperSetup.v1.1.1.exe) - Updated documentation and docs site download tables to include the Windows installer alongside the published Linux desktop packages
- Added full SQLite provider as an alternative to Supabase for completely local, zero-network credential storage
- Works in both browser/PWA and Electron desktop modes
- Browser/PWA stores the database locally in IndexedDB (with localStorage fallback)
- Electron desktop can additionally target a custom file path on disk
- No account, server, or internet connection required — ideal for fully offline and air-gapped use
- Added
src/integrations/database/sqlite-client.ts— browser-native SQL.js-backed SQLite engineSqliteQueryBuilder— Supabase-compatible query builder so all existingsupabase.from(...)callsites transparently route to SQLite with zero refactoring- In-memory database with IndexedDB persistence per named database key
- Full CRUD support:
select,insert,update,upsert,deletewith chained.eq(),.order(),.limit(),.single() - Automatic schema creation (
ensureSqliteSchema) on first open:credentials,vault_config, andcategoriestables with all indexes - Default categories seeded automatically on first-run: Development, Personal, Work, Social Media, Finance, Cloud Services, Security
- Added multi-provider routing in
src/integrations/supabase/client.ts:getDatabaseProvider()/saveDatabaseProvider()— persists provider choice inlocalStoragesupabaseexport now transparently delegates to the active provider (Supabase or SQLite)initializeSqliteProvider()andtestSqliteProviderConnection()helpers
- Added SQLite configuration UI in
Settings.tsx:- Database Provider selector (Supabase / SQLite)
- Optional SQLite path/name field (empty = default browser-local database)
- Provider-aware connection test and status messages
- Provider-aware setup instructions (SQLite auto-creates schema; Supabase requires SQL Editor run)
- Updated
DashboardSettings.tsxpassphrase reset instructions to show provider-specific steps:- SQLite users: guided to DB Browser for SQLite to edit
vault_config.bcrypt_hashdirectly - Supabase users: existing Supabase Dashboard-based reset flow unchanged
- SQLite users: guided to DB Browser for SQLite to edit
- Updated reset-local-config message to be provider-agnostic ("database connection settings")
- Added self-service multi-user registration flow with no admin involvement:
src/components/UserRegistration.tsxprovides username + passphrase registration with live username availability checks and passphrase confirmation- Username validation now enforces 3-50 characters with letters, numbers, hyphens, and underscores
- Registration creates an isolated vault per user and seeds default categories for that user context
- Added registration entrypoint in
PassphraseGate.tsx:- New Create New User action on the lock screen
- Successful registration immediately initializes/unlocks the new user vault
- Added user management UI in dashboard settings:
- New User Management area with registered-user listing (
vault_config.user_id) - Current user indicator and one-click user switching workflow
- Add New User action from user management that routes directly into registration flow
- New User Management area with registered-user listing (
- Added
VaultManager.registerNewUser(username, passphrase)for secure self-service onboarding:- Duplicate username protection
- Per-user vault creation (
raw_dek+bcrypt_hash) in existing zero-knowledge model - Per-user default category initialization
- Updated app security messaging to explicitly document:
- No admin backdoors
- Passphrase remains user-controlled
- Switching user context does not bypass passphrase verification
- Added SQLite-focused multi-user tests in
src/services/multi-user-sqlite.test.tscovering:- Creating multiple users in the same instance
- Per-user vault isolation and access boundaries
- Switching between user contexts with independent passphrase checks
- Fixed critical bug where
SqliteQueryBuilder.select()was overwriting the in-flight mutation action (insert,update,upsert,delete) withselect, causing vault creation to silently fail- Root cause: chained
.upsert({...}).select().single()— standard Supabase pattern for "write and return row" — was being treated as a plain SELECT; the query returned PGRST116 → "Failed to save vault configuration: Unknown error" - Fix:
select()no longer changes the action when a mutation has already been set, correctly matching Supabase client semantics - All other mutation chains (e.g.,
.insert().select()inEncryptedCredentialsApi) are also fixed by this change
- Root cause: chained
- Fixed empty categories dropdown when creating a new vault via SQLite
- Root cause:
ensureSqliteSchemacreated thecategoriestable but never seeded default rows — so the first-time vault creation had no categories to display - Fix: default categories are now seeded on first database initialisation when the table is empty
- Root cause:
- Added secure secret reveal in
CredentialDetailModalby decryptingsecret_blobwhen the vault is unlocked- Users can now inspect encrypted values directly from the detail view without entering edit mode
- Improved copy workflow in detail view for sensitive fields (password, API key, secret value, token, certificate)
- Existing eye/copy controls now work with encrypted-only records
- Added vault-state guidance in detail view
- Clear helper message when the vault is locked and encrypted values cannot be shown yet
- Improved detail modal width for better credential visibility on desktop
- Fixed horizontal overflow/cutoff in sensitive field rows
- Added robust wrapping for long revealed values (keys/secrets/certificates) so they stay within the modal instead of clipping
- Added
documentcredential type- Upload support in add/edit flows for common formats:
.pdf,.doc,.docx,.odt,.txt,.md - Uploaded files are stored in encrypted
secret_blobpayload as base64 + metadata (document_name,document_mime_type,document_size_bytes)
- Upload support in add/edit flows for common formats:
- Added
misccredential type- Dedicated large multiline secure field for scripts/commands and other non-standard sensitive text
- Added
certificateupload parity in edit flow (file upload + paste experience now aligned with add flow)
- Fixed type-specific secret leakage issue where unrelated secret keys could appear in other credential types
- Add/edit encryption paths now strictly encrypt only fields relevant to the selected
credential_type - Detail view now renders sensitive blocks conditionally by
credential_typeto prevent incorrect fields (for exampleAPI Keyshowing ondocumentrecords)
- Add/edit encryption paths now strictly encrypt only fields relevant to the selected
- Fixed document-save encryption reliability for new uploads by using type-scoped payload construction in add/edit submit flows
- Added secure download action in credential detail view for
documentcredentials - Added inline preview toggle (eye button) for text-like documents (
text/*,.txt,.md)- Binary formats (for example PDF/DOCX/ODT) intentionally remain download-only in current release
- Updated setup schema to allow new credential types in
credentials_credential_type_check:document,misc
- Added migration script for existing installations:
migration-add-document-misc-types.sql- Safely updates the
credential_typeCHECK constraint without recreating tables/data
- Updated in-app SQL surfaces:
- Setup screen now includes both full setup script and update script (copy + preview)
- Dashboard settings now includes a dedicated Database SQL tab with both scripts and upgrade warnings
- Added
Dockerfile– optimised multi-stage build (Node 22 Alpine builder → nginx 1.27 Alpine server)- Stage 1 compiles the Vite/React app; Stage 2 serves only the static output → lean final image
- WASM MIME type (
application/wasm) patched so argon2-browser works inside the container Cross-Origin-Opener-Policy: same-originandCross-Origin-Embedder-Policy: require-corpheaders added to satisfy SharedArrayBuffer requirements
- Added
nginx.conf– production-hardened nginx server block- SPA fallback routing (
try_files ... /index.html) for React Router - Gzip compression for JS/CSS/WASM/SVG/fonts
- Long-lived cache headers (
Cache-Control: public, immutable) for hashed assets - Security headers:
X-Frame-Options,X-Content-Type-Options,X-XSS-Protection,Referrer-Policy,Permissions-Policy /healthzendpoint for container health checks
- SPA fallback routing (
- Added
docker-compose.yml– single-command stack launch with configurableHOST_PORT(default8080)- Built-in
healthcheckusing the nginx/healthzendpoint - Optional Caddy reverse-proxy snippet (commented out) for automatic HTTPS
- Built-in
- Added
.dockerignore– excludesnode_modules/,dist/,electron/, VCS files, secrets, and tooling to keep the build context lean
- Added
electron/main.ts– Electron main process- Custom
app://protocol serves the compileddist/bundle with full SPA routing support - WASM
Content-Typepatched for argon2-browser inside the Electron sandbox Cross-Origin-Opener-Policy/Cross-Origin-Embedder-Policyinjected viasession.webRequestheaders- External link interception: all
https://links open in the system browser viashell.openExternal - Security hardening:
contextIsolation: true,nodeIntegration: false - macOS traffic-light title bar; auto-hiding menu bar on Windows/Linux
- Custom
- Added
electron/preload.ts– minimal context-bridge exposingwindow.keyperElectronto the rendererisElectron: trueflag for UI feature detectionplatformandversionfields
- Added
electron/tsconfig.json– TypeScript config targeting CommonJS (required for Electron main process) - Added electron scripts to
package.json:electron:compile– compileselectron/*.ts→electron-dist/*.jselectron:preview– build + compile + launch locallyelectron:dev– same but opens DevToolselectron:build– full cross-platform distributables via electron-builderelectron:build:linux/electron:build:win/electron:build:mac– platform-specific builds
- Added
electron-builder.yml– electron-builder configuration- Linux: AppImage (x64/arm64), deb (x64/arm64)
- macOS: DMG + zip (Universal / Intel + Apple Silicon)
- Added
electron^33.3.0andelectron-builder^25.1.8to devDependencies
- Added direct download links for Linux desktop installers (AppImage, deb x86_64, deb ARM64) hosted on Cloudflare R2 via the Keyper docs site
- Updated
.gitignore– addeddist-electron/andelectron-dist/output directories
-
Fixed Critical error "can't access property 'trim', t.token_value is undefined" when adding a second credential in the same session
- Root Cause:
resetForm()inAddCredentialModalwas missingtoken_valueandcertificate_datafields, leaving them asundefinedafter the first save - Fix: Added the two missing fields back to
resetForm()so all state is properly cleared between submissions
- Root Cause:
-
Fixed Critical error "could not find the 'api_key' column of 'credentials' in the schema cache" when editing a credential
- Root Cause:
EditCredentialModal.handleSubmit()was spreading the entireformDataobject directly into the Supabase.update()call, including legacy column names (api_key,password,secret_value, etc.) that do not exist in the current schema — all sensitive data lives insecret_blob - Fix: Rewrote the submit handler to build an explicit update object with only valid DB columns, and properly encrypt sensitive data into
secret_blobusing the vault
- Root Cause:
-
Improved
EditCredentialModalnow correctly decrypts existingsecret_blobdata when the edit form opens, so current secret values are pre-populated and editable -
Improved
EditCredentialModalnow properly handles all five credential types with their correct sensitive field names:password(login),api_key(api_key),secret_value(secret),token_value(token),certificate_data(certificate) — previouslytokenwas incorrectly sharing thesecret_valuefield andcertificatetype had no dedicated input
- Added "No expiration" checkbox next to the Expires At date field in
AddCredentialModal- Checking it clears any selected date and disables the date picker (visually greyed out)
- Unchecking re-enables the date picker for normal use
- Resets automatically when the form is cleared after a save
- Updated Supabase API key field label from
"Supabase Anon Key"to"Supabase Anon or Publishable Key"to reflect Supabase's updated naming convention (both key types remain fully supported)- Updated in: Settings configuration screen, SQL setup script comment, and database setup wizard description
- Added Stunning gradient KEYPER ASCII art banner for professional startup experience
- Beautiful Typography: Large block-letter KEYPER logo in gradient cyan/blue colors
- Brand Colors: Matching cyan/blue gradient that complements the app's glassmorphism UI theme
- Clean Layout: Removed cluttered box borders for modern, minimal aesthetic
- Professional Branding: Enhanced Pink Pixel branding with "Dream it, Pixel it" tagline
- Fixed Node.js deprecation warning (DEP0190) for enhanced security
- Eliminated Insecure
shell: true+ arguments array combination - Implemented Cross-platform spawn solution for Windows/Unix systems
- Enhanced Security by preventing argument injection vulnerabilities
- Improved Command execution reliability across all platforms
- Eliminated Insecure
- Added Platform detection for optimal command execution strategy:
- Windows: Uses properly escaped command string with
shell: true - Unix/Linux/Mac: Uses secure argument array with
shell: false
- Windows: Uses properly escaped command string with
- Enhanced Error handling and process management
- Maintained Full backward compatibility with existing CLI functionality
- Improved Developer experience with clean, warning-free startup
- Enhanced Visual brand consistency between CLI and web application
- Removed Annoying deprecation warnings during server startup
- Improved Professional appearance for enterprise deployments
- Maintained All existing CLI functionality and features
- Eliminated Potential command injection attack vectors
- Enhanced Cross-platform security posture
- Improved Node.js compliance with latest security recommendations
- Maintained Zero-trust architecture principles
- Fixed Critical issue preventing local Supabase instances from connecting
- Removed Overly restrictive URL validation in
createTestSupabaseClient - Enhanced Connection logic to accept any valid HTTP/HTTPS URL
- Added Comprehensive support for localhost, IP addresses, and custom domains
- Improved Error messages and debugging information for connection issues
- Removed Overly restrictive URL validation in
- Added Support for all local and self-hosted Supabase deployments:
- ✅ Localhost:
http://localhost:54321,https://localhost:8443 - ✅ IP Addresses:
http://192.168.1.100:8000,http://127.0.0.1:54321 - ✅ Private Networks:
http://10.0.0.5:54321,http://172.17.0.1:8000 - ✅ Docker Networks: Complete support for all Docker IP ranges (172.16-31.*)
- ✅ Custom Domains:
https://supabase.mydomain.com,https://db.company.local - ✅ Supabase Cloud: Existing
*.supabase.coinstances continue to work seamlessly
- ✅ Localhost:
- Enhanced CSP configuration with intelligent environment detection:
- Development: Fully permissive for maximum flexibility during development
- Self-hosted: Balanced security with custom domain support for production
- Cloud: Optimized security for Supabase Cloud deployments
- Added Dynamic CSP selection based on configured database credentials
- Improved Network support for all private IP ranges and custom domains
- Added
hasCustomSupabaseCredentials()helper function for clean configuration detection - Enhanced Connection validation with informational logging instead of blocking
- Improved Error handling and debugging information throughout connection flow
- Refactored Hardcoded configuration checks to use proper helper functions
- Modified
src/integrations/supabase/client.ts:- Removed restrictive hostname validation that blocked valid URLs
- Added comprehensive IP range support for private networks
- Enhanced logging for better debugging experience
- Updated
src/components/SelfHostedDashboard.tsx:- Replaced hardcoded string comparisons with helper functions
- Improved configuration state detection
- Enhanced
src/security/ContentSecurityPolicy.ts:- Added three-tier CSP system (Development, Self-hosted, Production)
- Comprehensive network range support for all deployment scenarios
- Dynamic policy selection based on configuration
| Instance Type | Before v1.0.6 | After v1.0.6 |
|---|---|---|
Supabase Cloud (*.supabase.co) |
✅ Working | ✅ Working |
Localhost (http://localhost:*) |
❌ Blocked | ✅ FIXED |
Local IP (http://192.168.1.100:*) |
❌ Blocked | ✅ FIXED |
Custom Domain (https://db.company.com) |
❌ Blocked | ✅ FIXED |
Docker Network (http://172.17.*:*) |
❌ Blocked | ✅ FIXED |
- ✅ Backward Compatible: All existing Supabase Cloud setups continue working unchanged
- ✅ Security Maintained: Enhanced CSP policies maintain strong security posture
- ✅ No Breaking Changes: Seamless upgrade path with zero configuration changes required
- ✅ Enhanced Debugging: Better error messages and connection diagnostics
- Added
SUPABASE_FIXES.md- Comprehensive documentation of all fixes applied - Updated Connection troubleshooting guides with new supported formats
- Enhanced Self-hosting instructions with local instance setup examples
- Resolved Connection failures for local Supabase instances
- Eliminated "URL does not appear to be a Supabase instance" errors
- Enabled Full self-hosting flexibility with any domain or IP configuration
- Improved Developer experience with better error messages and debugging
- Added Simplified bcrypt-only master passphrase authentication
- Eliminated complex Argon2/AES key derivation for passphrase validation
- Implemented direct bcrypt hash verification for instant authentication
- Removed all backdoors, admin overrides, and security vulnerabilities
- Created user-controlled passphrase reset via direct database access
- Enhanced Security through elimination of attack vectors
- Added
docs/EMERGENCY_PASSPHRASE_RESET.md- Comprehensive reset guide- Instructions for bcrypt hash generation using online tools
- Step-by-step database update procedure via Supabase dashboard
- Security explanations why this approach is safe and user-controlled
- Troubleshooting section for common reset issues
- Simplified Vault encryption system:
- New Users:
raw_dek(base64) +bcrypt_hashstorage - Legacy Users: Continue using existing
wrapped_deksystem (backwards compatible) - Dual Support: Automatic detection and handling of both vault formats
- Migration Path: Optional upgrade path for existing users
- New Users:
- Removed Emergency access systems and backdoors:
- Deleted
src/security/HatchGate.ts- Eliminated backdoor access - Removed
src/components/ResetKeyper.tsx- No admin reset capability - Cleaned All references to emergency admin access
- Updated Documentation to reflect new security-first approach
- Deleted
- Created
src/crypto/bcrypt.ts- Secure bcrypt utility functions - Enhanced
src/services/VaultStorage.ts- Dual format support - Updated
src/services/VaultManager.ts- Smart vault type detection - Simplified
src/services/SecureVault.ts- Maintains legacy compatibility - Improved Type definitions with legacy/new vault config types
- Updated
supabase-setup.sqlandsrc/components/Settings.tsx:- Added
raw_dek TEXTcolumn (nullable for backwards compatibility) - Enhanced
bcrypt_hash TEXTcolumn for new passphrase system - Maintained
wrapped_dek JSONBfor existing users - Secured All PostgreSQL functions with proper
SECURITY DEFINERsettings
- Added
- Created
migration-bcrypt.sql- Database migration script- Adds new columns to existing vault_config table
- Provides detailed migration instructions for existing users
- Maintains full backwards compatibility
- Guides users through optional upgrade process
- New Users: Automatic bcrypt-only system with instant reset capability
- Existing Users: No changes required, everything continues working
- Reset Process: Simple 4-step process using any bcrypt generator website
- No Downtime: Seamless deployment with zero breaking changes
- Eliminated All potential backdoors and admin overrides
- Simplified Attack surface by removing complex key derivation chains
- Enhanced User control - only database owner can reset passphrases
- Maintained Strong AES-256-GCM encryption for actual credential data
- Preserved Zero-knowledge architecture principles
- Removed All emergency access and backdoor documentation
- Added User-controlled passphrase reset instructions
- Updated Security model documentation throughout project
- Enhanced Setup instructions with new migration procedures
- Fixed PostgreSQL function search_path security warnings (function_search_path_mutable)
- update_updated_at_column: Added
SET search_path = ''security parameter - get_credential_stats: Added
SET search_path = ''+ fully qualified schema references - check_rls_status: Added
SET search_path = ''+ fully qualified schema references - Protection: Prevents search path injection attacks and ensures consistent behavior
- Compliance: Meets PostgreSQL security best practices and OWASP guidelines
- update_updated_at_column: Added
- Added
rls-security-fixes.sql- Standalone security patch for existing databases - Updated
supabase-setup.sql- Main setup script now includes secure function definitions - Improved All functions now use
SECURITY DEFINERwith empty search_path - Qualified All database object references use explicit
schema.tablenotation - Documented Comprehensive security implementation details in updated files
- Search Path Security: All PostgreSQL functions now set
search_path = ''to prevent path manipulation - Schema Qualification: Database objects referenced with explicit
public.tablenameformat - Consistent Context: Functions execute with predictable, secure environment
- Best Practices: Aligned with PostgreSQL security recommendations and industry standards
- Updated
RLS_FIXES_NEEDED.md- Now shows resolved status with implementation details - Added Security fix implementation guide with verification queries
- Enhanced Database setup instructions with security considerations
- Added Emergency diagnostic and reset system for stuck configurations
- HatchGate.ts: Session-based temporary access control with short-lived session TTL
- ResetKeyper.tsx: Comprehensive diagnostic page for troubleshooting
- Hidden Route: Secure diagnostic route only accessible when armed
- Health Checks: Database table verification and connection testing
- Config Reset: Selective clearing of Keyper configuration keys
- Origin Reset: Complete site data clearing for extreme cases
- Added Obscurity-based emergency access without compromising authentication
- Added Session storage with automatic expiration for temporary access
- Added Optional admin marker requirement for additional protection
- Added Professional ops procedures with encryption recommendations
- Security Note: Emergency system uses security-by-obscurity, not authentication bypass