diff --git a/TODO.md b/TODO.md index 2e86965..cb24a4a 100644 --- a/TODO.md +++ b/TODO.md @@ -8,7 +8,7 @@ prioritized from most critical (top) to least critical (bottom). ### Functions accepting bare []byte for sensitive data - [x] **1. Secret.Save accepts unprotected data**: `internal/secret/secret.go:67` - `Save(value []byte, force bool)` - ✓ REMOVED - deprecated function deleted -- [ ] **2. EncryptWithPassphrase accepts unprotected data**: `internal/secret/crypto.go:73` - `EncryptWithPassphrase(data []byte, passphrase *memguard.LockedBuffer)` - the data parameter should be LockedBuffer +- [x] **2. EncryptWithPassphrase accepts unprotected data**: `internal/secret/crypto.go:73` - `EncryptWithPassphrase(data []byte, passphrase *memguard.LockedBuffer)` - ✓ FIXED - now accepts LockedBuffer for data - [ ] **3. storeInKeychain accepts unprotected data**: `internal/secret/keychainunlocker.go:469` - `storeInKeychain(itemName string, data []byte)` - stores secrets in keychain with unprotected data - [ ] **4. gpgEncryptDefault accepts unprotected data**: `internal/secret/pgpunlocker.go:351` - `gpgEncryptDefault(data []byte, keyID string)` - encrypts unprotected data diff --git a/internal/secret/keychainunlocker.go b/internal/secret/keychainunlocker.go index 8979455..4babe5b 100644 --- a/internal/secret/keychainunlocker.go +++ b/internal/secret/keychainunlocker.go @@ -409,8 +409,12 @@ func CreateKeychainUnlocker(fs afero.Fs, stateDir string) (*KeychainUnlocker, er return nil, fmt.Errorf("failed to marshal keychain data: %w", err) } + // Create a secure buffer for keychain data + keychainDataBuffer := memguard.NewBufferFromBytes(keychainDataBytes) + defer keychainDataBuffer.Destroy() + // Step 8: Store data in keychain - if err := storeInKeychain(keychainItemName, keychainDataBytes); err != nil { + if err := storeInKeychain(keychainItemName, keychainDataBuffer); err != nil { return nil, fmt.Errorf("failed to store data in keychain: %w", err) } @@ -466,14 +470,17 @@ func validateKeychainItemName(itemName string) error { } // storeInKeychain stores data in the macOS keychain using the security command -func storeInKeychain(itemName string, data []byte) error { +func storeInKeychain(itemName string, data *memguard.LockedBuffer) error { + if data == nil { + return fmt.Errorf("data buffer is nil") + } if err := validateKeychainItemName(itemName); err != nil { return fmt.Errorf("invalid keychain item name: %w", err) } cmd := exec.Command("/usr/bin/security", "add-generic-password", //nolint:gosec "-a", itemName, "-s", itemName, - "-w", string(data), + "-w", data.String(), "-U") // Update if exists if err := cmd.Run(); err != nil {