File tree Expand file tree Collapse file tree 2 files changed +14
-16
lines changed
Expand file tree Collapse file tree 2 files changed +14
-16
lines changed Original file line number Diff line number Diff line change @@ -4,7 +4,7 @@ import { ApiKeyStorage } from './api-key-storage'
44describe ( 'ApiKeyStorage' , ( ) => {
55 let storage : ApiKeyStorage
66 let localStorageMock : Record < string , string >
7- const mockUserAgent = 'Mozilla/5.0 (Test) TestBrowser/1.0 '
7+ const testKeyMaterial = 'test-key-material-for-encryption '
88
99 beforeEach ( ( ) => {
1010 // Mock localStorage
@@ -27,19 +27,8 @@ describe('ApiKeyStorage', () => {
2727 key : vi . fn ( ) ,
2828 } )
2929
30- // Mock navigator.userAgent for consistent encryption key derivation
31- // Use Object.create to preserve the navigator prototype chain for jsdom in CI
32- const navigatorMock = Object . create (
33- Object . getPrototypeOf ( globalThis . navigator ) ,
34- Object . getOwnPropertyDescriptors ( globalThis . navigator ) ,
35- )
36- Object . defineProperty ( navigatorMock , 'userAgent' , {
37- value : mockUserAgent ,
38- configurable : true ,
39- } )
40- vi . stubGlobal ( 'navigator' , navigatorMock )
41-
42- storage = new ApiKeyStorage ( )
30+ // Use constructor parameter for consistent key derivation in tests
31+ storage = new ApiKeyStorage ( testKeyMaterial )
4332 } )
4433
4534 afterEach ( ( ) => {
Original file line number Diff line number Diff line change @@ -13,15 +13,24 @@ interface EncryptedData {
1313export class ApiKeyStorage {
1414 private encoder = new TextEncoder ( )
1515 private decoder = new TextDecoder ( )
16+ private keyMaterialOverride ?: string
17+
18+ /**
19+ * @param keyMaterialOverride - Optional override for key derivation (for testing only)
20+ */
21+ constructor ( keyMaterialOverride ?: string ) {
22+ this . keyMaterialOverride = keyMaterialOverride
23+ }
1624
1725 /**
1826 * Derive a crypto key from the user agent string
1927 * This provides basic obfuscation (not cryptographically secure against determined attackers)
2028 * but protects against casual inspection of localStorage
2129 */
2230 private async deriveCryptoKey ( ) : Promise < CryptoKey > {
23- // Use user agent as key material (stable across sessions)
24- const keyMaterial = this . encoder . encode ( navigator . userAgent + 'bugzilla-kanban-salt' )
31+ // Use user agent as key material (stable across sessions), or override for testing
32+ const keySource = this . keyMaterialOverride ?? navigator . userAgent
33+ const keyMaterial = this . encoder . encode ( keySource + 'bugzilla-kanban-salt' )
2534
2635 // Import as raw key material
2736 const importedKey = await crypto . subtle . importKey (
You can’t perform that action at this time.
0 commit comments