* Migrate create and edit operations to use SDK for ciphers
* WIP: Adds admin call to edit ciphers with SDK
* Add client version to SDK intialization settings
* Remove console.log statements
* Adds originalCipherId and collectionIds to updateCipher
* Update tests for new cipehrService interfaces
* Rename SdkCipherOperations feature flag
* Add call to Admin edit SDK if flag is passed
* Add tests for SDK path
* Revert changes to .npmrc
* Remove outdated comments
* Fix feature flag name
* Fix UUID format in cipher.service.spec.ts
* Update calls to cipherService.updateWithServer and .createWithServer to new interface
* Update CLI and Desktop to use new cipherSErvice interfaces
* Fix tests for new cipherService interface change
* Bump sdk-internal and commercial-sdk-internal versions to 0.2.0-main.439
* Fix linting errors
* Fix typescript errors impacted by this chnage
* Fix caching issue on browser extension when using SDK cipher ops.
* Remove commented code
* Fix bug causing race condition due to not consuming / awaiting observable.
* Add missing 'await' to decrypt call
* Clean up unnecessary else statements and fix function naming
* Add comments for this.clearCache
* Add tests for SDK CipherView conversion functions
* Replace sdkservice with cipher-sdk.service
* Fix import issues in browser
* Fix import issues in cli
* Fix type issues
* Fix type issues
* Fix type issues
* Fix test that fails sporadically due to timing issue
* Update master password policy dialog to limit the minimum length to 128
* Update master password policy to use dynamic maximum length from Utils
* Add unit tests for MasterPasswordPolicyComponent to validate password length constraints and scoring
* PM-13632: Enable sign in with passkeys in the browser extension
* Refactor component + Icon fix
This commit refactors the login-via-webauthn commit as per @JaredSnider-Bitwarden suggestions. It also fixes an existing issue where Icons are not displayed properly on the web vault.
Remove old one.
Rename the file
Working refactor
Removed the icon from the component
Fixed icons not showing. Changed layout to be 'embedded'
* Add tracking links
* Update app.module.ts
* Remove default Icons on load
* Remove login.module.ts
* Add env changer to the passkey component
* Remove leftover dependencies
* PRF Unlock
Cleanup and testes
* Workaround prf type missing
* Fix any type
* Undo accidental cleanup to keep PR focused
* Undo accidental cleanup to keep PR focused
* Cleaned up public interface
* Use UserId type
* Typed UserId and improved isPrfUnlockAvailable
* Rename key and use zero challenge array
* logservice
* Cleanup rpId handling
* Refactor to separate component + icon
* Moved the prf unlock service impl.
* Fix broken test
* fix tests
* Use isChromium
* Update services.module.ts
* missing , in locales
* Update desktop-lock-component.service.ts
* Fix more desktoptests
* Expect a single UnlockOption from IdTokenResponse, but multiple from sync
* Missing s
* remove catches
* Use new control flow in unlock-via-prf.component.ts
Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
* Changed throw behaviour of unlockVaultWithPrf
* remove timeout comment
* refactired webauthm-prf-unlock.service internally
* WebAuthnPrfUnlockServiceAbstraction -> WebAuthnPrfUnlockService
* Fixed any and bad import
* Fix errors after merge
* Added missing PinServiceAbstraction
* Fixed format
* Removed @Inject()
* Fix broken tests after Inject removal
* Return userkey instead of setting it
* Used input/output signals
* removed duplicate MessageSender registration
* nit: Made import relative
* Disable onPush requirement because it would need refactoring the component
* Added feature flag (#17494)
* Fixed ById from main
* Import feature flag from file
* Add missing test providers for MasterPasswordLockComponent
Add WebAuthnPrfUnlockService and DialogService mocks to fix test failures
caused by UnlockViaPrfComponent dependencies.
---------
Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
* Always store auto user key on CLI
* update unit tests
* prevent bad vault timeout state
* Update libs/key-management/src/key.service.ts
Co-authored-by: Bernd Schoolmann <mail@quexten.com>
---------
Co-authored-by: Bernd Schoolmann <mail@quexten.com>
* Support v2 encryption for JIT Password signups
* TDE set master password split
* update sdk-internal dependency
* moved encryption v2 to InitializeJitPasswordUserService
* remove account cryptographic state legacy states from #18164
* legacy state comments
* sdk update
* unit test coverage
* consolidate do SetInitialPasswordService
* replace legacy master key with setLegacyMasterKeyFromUnlockData
* typo
* web and desktop overrides with unit tests
* early return
* compact validation
* simplify super prototype
* [PM-21774] Adjust icon and tooltip for protected Sends on the Sends list page
* [PM-21774] Update Sent table UI stories
* [PM-21774] Fix Send table UI story
* Add logs for debugging in phishing-detection-settings.service
* Update phishing data service to separate web addresses from meta data for performant writes. Store compressed string instead of array
* Cleanup
* Updated test cases
* Cleanup comments
* Fix fallback encoding/decoding mismatch
* Fix type checking
Migrated vault filters to new v3 vault's navigation
* Decoupled existing vault filtering from vault component by using routed params with routed-vault-filter-bridge
* Converted vault filters to standalone components
* Removed extending filter Base Components from deprecated /libs/angular library and handled logic directly
* Moved shared 'models' and 'services' directories from web-vault into /libs/vault
* [FIX] Pass more inclusive user verification Boolean to `setAbortTimeout`
* Update `setAbortTimeout` user verification parameter type
* Fix lint issue
---------
Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
* [deps] Platform: Update electron-store to v11
* wip-fix: all imports failing due to nodenext switch
* fix: desktop tsconfig not working properly
Renderer tsConfigPath was wrong so it defaulted to the base `tsconfig.json` which
included every single sourcefile into the angular artifact. This caused errors
with ESM modules which behave differently on node and needed a separate `tsconfig.json`
configuration.
* fix: revert some of the changes made to tools code
* fix: ESM import in tests
* chore: use consistent path
* feat: actually use custom tsconfig for preload
* fix: use correct entry point in tsconfig.main.json
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Andreas Coroiu <andreas.coroiu@gmail.com>
Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>
* finalize new UI elements for archive/unarchive
* add tests
* add missing service
* add tests
* updates to edit and view pages
* use structureClone
* fix lint
* fix typo
* clean up return types
* fixes to archive UI
* fix tests
* use @if and userId$
* remove feature flag from lock component
* Add missing windowHidden desktop feature
* Remove the flag from CLI unlock
* Remove the flag from enum file
* prevent redundant cache updates on account switch
Remove automatic cache update triggering that caused UI freezes when
switching to accounts with phishing detection access.
Root cause: The update$ observable used startWith(undefined) which
triggered an immediate cache refresh whenever a new subscription was
created. On account switch, phishingDetectionSettingsService.on$ emits
true, creating a new subscription and triggering a full ~800K entry
fetch that blocks the UI thread.
Fix:
- Remove startWith(undefined) to prevent auto-triggering on subscription
- Add MIN_UPDATE_INTERVAL (5 min) constant for cache freshness checks
- Add _updateInProgress flag to prevent concurrent updates
- Add filter() to skip updates when one is already in progress
- Add cache freshness check (skip if updated within 5 minutes)
- Add finalize() to reliably reset _updateInProgress flag (per ADR)
- Replace share() with shareReplay() to prevent duplicate work
- Add triggerUpdateIfNeeded() public method for explicit update requests
The scheduled 24-hour update interval is unaffected - it still calls
_triggerUpdate$.next() via the task scheduler.
* trigger cache updates asynchronously on account switch
Update PhishingDetectionService to explicitly trigger cache updates
when phishing detection becomes active for an account, using a
non-blocking pattern.
Changes:
- Add call to phishingDataService.triggerUpdateIfNeeded() when on$ emits true
- Use of(null).pipe(delay(0)) to defer update to next event loop tick
- This prevents the update from blocking the account switch UI flow
The delay(0) pattern is preferred over setTimeout per codebase conventions
(RxJS over native JS). The subscription auto-completes since of() emits
once and completes, so no manual cleanup is needed.
Combined with the previous commit's safeguards (cache freshness check,
concurrent update prevention), this ensures:
1. Account switch completes immediately (non-blocking trigger)
2. Cache updates only run when actually needed (< 5 min freshness)
3. Concurrent updates are prevented (_updateInProgress flag)
Fixes: PM-30319
* decouple cache update subscription from UI event merge
Move phishingDataService.update$ to a separate subscription outside the
merge() stream to prevent blocking the service worker during critical
initialization and account switch flows.
Background:
The service worker is single-threaded. When the phishing cache update
runs, it downloads a 25MB file and parses 800K entries using .split(),
which is CPU-intensive synchronous work. During this parsing, the
service worker cannot respond to popup requests, causing the extension
UI to appear frozen when the user clicks the extension icon.
Previously, update$ was included in the merge() alongside UI event
handlers (onTabUpdated$, onContinueCommand$, onCancelCommand$). When
on$ emitted true (user has phishing access), the merge subscription
was created as part of the same synchronous flow, coupling the heavy
cache work with the UI event setup.
Changes:
- Create separate updateSub subscription at initialization
- Remove update$ from merge() - now only contains UI event streams
- Keep delay(0) trigger for triggerUpdateIfNeeded()
How delay(0) works:
JavaScript's event loop must complete all synchronous code before
processing async callbacks. delay(0) schedules the trigger for the
next event loop tick, meaning:
1. initialize() completes and returns
2. Service worker is 'free' to handle other tasks
3. Next tick: triggerUpdateIfNeeded() fires
4. Cache update runs in background
The cache parsing will still block the thread when it eventually runs,
but this is now decoupled from the critical initialization path. The
window where blocking can affect user interaction is minimized.
PM-30319
* comment
* account for new changes in spec file
* prevent UI blocking during cache updates
Problem:
- Switching accounts caused 5+ second UI freeze
- Even when data unchanged, 789K entries were rewritten to IndexedDB
- Set was rebuilt from 789K entries on every state emission
Solution:
- Skip state update when checksum matches (return null instead of full data)
- Cache Set in memory, only rebuild when checksum changes
- Track last check time in memory instead of state
- Use streaming fetch to prevent Firefox memory explosion
- Add comprehensive logging for debugging
Performance improvement:
- Checksum match: ~5 seconds → ~10ms (no blocking)
- Full update: Still required when data changes, but with streaming
* pre-populate cache on install/update and optimize Set building
Problem:
Premium users experienced a 5+ second UI freeze on first login after
install because the phishing list (~63MB, 789K entries) was downloaded
synchronously when phishing detection was enabled.
Solution:
1. Pre-populate cache on extension install/update
- Added triggerPhishingCacheUpdate() to MainBackground
- RuntimeBackground calls this on "install" and "update" events
- Cache is ready before user logs in, eliminating first-login lag
2. Chunked Set building for UI responsiveness
- Build Set in 50K-entry chunks with event loop yields
- Changed from synchronous map() to async switchMap() + buildSetInChunks()
- Prevents UI blocking when Set is rebuilt from cached data
3. Streaming with yields
- Added yield after each network chunk during streaming fetch
- Keeps service worker responsive to popup messages during download
4. Log cleanup for production
- Converted verbose debugging logs from info → debug level
- Kept important operational events (daily/full updates) at info
- Removed timing logs and progress banners
- Fixed comment accuracy: 100MB → 63MB uncompressed
Performance impact:
- First login after install: 5+ seconds → near-instant (cache pre-populated)
- Set rebuild: non-blocking via chunked processing
- Subsequent updates: already optimized via checksum matching
* spec
* add allowlist for bare amazon.com domain
Problem:
The upstream Phishing.Database contains a false positive entry
`https://www.Amazon.com` (line 666495), causing the real Amazon
website to be incorrectly blocked.
Solution:
Add BARE_DOMAIN_ALLOWLIST that skips blocking for exact hostname
matches (amazon.com, www.amazon.com) when the URL has no path,
query, or hash. This protects users from false positives while
still detecting phishing URLs that use Amazon in paths or
subdomain tricks.
Allowed:
- https://amazon.com
- https://www.amazon.com
Still blocked:
- https://amazon.com/phishing/path
- https://amazon.com-malicious.xyz
- https://fake.com/amazon.com/steal
* logging
* update our links source url
* Fix Chrome memory leak in phishing detection service
* reduce memory leaks
* optimize phishing detection performance and fix memory leaks
This commit addresses critical performance issues and memory leaks in the
phishing detection feature, particularly for non-premium users and during
extension reloads.
Storage Isolation:
- Created BrowserIndexedDbStorageService for large data storage
- Separated PHISHING_DATA_DISK (60MB+ phishing URLs) from PHISHING_DETECTION_DISK
- Prevents popup from loading large dataset when accessing small settings
- Fixed UI freeze when navigating to Settings -> Account security -> back arrow
Lazy Loading Optimizations:
- Converted _cachedState, _webAddresses$, and update$ to lazy getters
- Only accesses IndexedDB when phishing detection is actually used
- Prevents blocking service worker initialization on extension reload
- Added guard in triggerUpdateIfNeeded() to skip if no observers
Performance Improvements:
- Modified buildEnabledPipeline$() to check available$ first
- Uses startWith(true) to emit immediately, preventing on$ from blocking
- Skips IndexedDB reads for non-premium users during unlock/account switch
- Prevents 3+ second UI freezes for non-premium users
Memory Leak Fixes:
- Added static interval cleanup to prevent accumulation on service recreation
- Fixed tab listener cleanup by storing bound handler reference
- Fixed triggerUpdateSub subscription cleanup on account switches
- Prevents exponential memory growth from undestroyed subscriptions
Test Fixes:
- Updated tests to set up available$ prerequisites before testing enabled$
- Fixed tests to wait for actual state values after startWith(true) emission
- Uses filter() to wait for expected state values in async tests
Files Changed:
- apps/browser/src/platform/services/browser-indexed-db-storage.service.ts (new)
- apps/browser/src/platform/storage/browser-storage-service.provider.ts
- apps/browser/src/dirt/phishing-detection/services/phishing-data.service.ts
- apps/browser/src/dirt/phishing-detection/services/phishing-detection.service.ts
- apps/browser/src/background/runtime.background.ts
- libs/common/src/dirt/services/phishing-detection/phishing-detection-settings.service.ts
- libs/common/src/dirt/services/phishing-detection/phishing-detection-settings.service.spec.ts
- libs/state/src/core/state-definitions.ts
- libs/storage-core/src/client-locations.ts
* fix test type errors
* remove allowlist
* storage isolation revert
The initial implementation of storage isolation was used to fix a specific navigation scenario that lead to freezing of the ui ("Settings → Account Security" and clicking the back button)
Why disk-large instead of memory-large-object:
- **Problem**: Users experienced infinite loading (2+ minute freezes) when navigating to "Settings → Account Security" and clicking the back button. The Popup would freeze because `chrome.storage.local` broadcasts 60MB writes to all contexts, causing the Popup to deserialize data it never requested.
- **Fix**: Created `disk-large` storage location using native IndexedDB, which persists data (unlike `memory-large-object`) and doesn't broadcast events (unlike `chrome.storage.local`), isolating large datasets from the Popup context.
**Key Difference:**
- `memory-large-object`: **Non-persistent** in-memory storage. Data is lost when the service worker restarts or the extension reloads.
- `disk-large`: **Persistent** storage using native IndexedDB. Data survives service worker restarts and extension reloads.
**Why We Need Persistence:**
The phishing dataset (~60MB, 780K entries) must persist across:
- Service worker restarts (Chrome terminates service workers after inactivity)
- Extension reloads/updates
- Browser restarts
If we used `memory-large-object`, the extension would need to re-download the entire 60MB dataset every time the service worker restarts, which happens frequently in Chrome. This would:
1. Waste bandwidth (60MB downloads on every restart)
2. Cause UI freezes on every restart (same problem we're trying to fix)
3. Fail offline scenarios
**Why Not Use Existing `disk` Location:**
The existing `"disk"` location uses `chrome.storage.local`, which has a critical flaw for large datasets:
- **Event Broadcasting**: Any write to `chrome.storage.local` triggers `onChanged` events broadcast to **all** extension contexts (Background, Popup, Sidebar)
- **The UI/UX Problem**:
- Users experienced **infinite loading** or **2+ minute freezes** when navigating to "Settings → Account Security" and clicking the back button
- When Background writes 60MB, Chrome serializes and IPCs it to Popup, causing Popup's main thread to freeze while deserializing this massive object, even if Popup never requested the data
- The Popup would become completely unresponsive, showing a spinning cursor or blank screen
- **The Fix**: Native IndexedDB doesn't broadcast events across processes, isolating the storage so Background can write 60MB without disturbing the Popup
* remove implementation comments from jsdoc
* renaming
* new domains source
* remove unnecessary complexity from buildEnabledPipeline and remove all IndexedDB references
* fix pre-population on install/update
* handle null webAddresses
---------
Co-authored-by: maxkpower <mpower@bitwarden.com>
* Front end changes to disable SM ads for users
* fixing failing tests
* Update libs/common/src/admin-console/models/response/organization.response.ts
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* fixing merge conflicts
* claude suggestion
* adding feature flag for disable sm ads on clients
* fixing tests
---------
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* add callout to vault-items for non premium users, add upgrade premium flow
* add archive badge to item details only for desktop
* update desktop edit item save for unarchive
* updated success toast for edited archive item non premium
* Add creationDate of account to AccountInfo
* Added initialization of creationDate.
* Removed extra changes.
* Fixed tests to initialize creation date
* Added helper method to abstract account initialization in tests.
* More test updates.
* Linting
* Additional test fixes.
* Fixed spec reference
* Fixed imports
* Linting.
* Fixed browser test.
* Modified tsconfig to reference spec file.
* Fixed import.
* Removed dependency on os. This is necessary so that the @bitwarden/common/spec lib package can be referenced in tests without node.
* Revert "Removed dependency on os. This is necessary so that the @bitwarden/common/spec lib package can be referenced in tests without node."
This reverts commit 669f6557b6.
* Updated stories to hard-code new field.
* Removed changes to tsconfig
* Revert "Removed changes to tsconfig"
This reverts commit b7d916e8dc.
* Updated to use Date
* Updated to use Date on sync.
* Changes to tests that can't use mock function
* Prettier updates
* Update equality to handle Date type.
* Change to type comparison.
* Simplified equality comparison to just use properties.
* Added comment.
* Updated comment to reference Date.
* Added back in internal method tests.