1
0
forked from sneak/secret

fix: non-darwin KeychainUnlocker stub returns errors instead of panicking

The stub previously panicked on all methods including NewKeychainUnlocker,
which is called from vault code when processing keychain-type unlocker
metadata. This caused crashes on Linux/Windows when a vault synced from
macOS contained keychain unlockers.

Now returns proper error values, allowing graceful degradation and
cross-platform vault portability.
This commit is contained in:
clawbot 2026-02-08 12:05:38 -08:00
parent 128c53a11d
commit 4419ef7730

View File

@ -4,6 +4,8 @@
package secret package secret
import ( import (
"fmt"
"filippo.io/age" "filippo.io/age"
"github.com/awnumar/memguard" "github.com/awnumar/memguard"
"github.com/spf13/afero" "github.com/spf13/afero"
@ -22,52 +24,59 @@ type KeychainUnlocker struct {
fs afero.Fs fs afero.Fs
} }
// GetIdentity panics on non-Darwin platforms var errKeychainNotSupported = fmt.Errorf("keychain unlockers are only supported on macOS")
// GetIdentity returns an error on non-Darwin platforms
func (k *KeychainUnlocker) GetIdentity() (*age.X25519Identity, error) { func (k *KeychainUnlocker) GetIdentity() (*age.X25519Identity, error) {
panic("keychain unlockers are only supported on macOS") return nil, errKeychainNotSupported
} }
// GetType panics on non-Darwin platforms // GetType returns the unlocker type
func (k *KeychainUnlocker) GetType() string { func (k *KeychainUnlocker) GetType() string {
panic("keychain unlockers are only supported on macOS") return "keychain"
} }
// GetMetadata panics on non-Darwin platforms // GetMetadata returns the unlocker metadata
func (k *KeychainUnlocker) GetMetadata() UnlockerMetadata { func (k *KeychainUnlocker) GetMetadata() UnlockerMetadata {
panic("keychain unlockers are only supported on macOS") return k.Metadata
} }
// GetDirectory panics on non-Darwin platforms // GetDirectory returns the unlocker directory
func (k *KeychainUnlocker) GetDirectory() string { func (k *KeychainUnlocker) GetDirectory() string {
panic("keychain unlockers are only supported on macOS") return k.Directory
} }
// GetID returns the unlocker ID // GetID returns the unlocker ID
func (k *KeychainUnlocker) GetID() string { func (k *KeychainUnlocker) GetID() string {
panic("keychain unlockers are only supported on macOS") return fmt.Sprintf("%s-keychain", k.Metadata.CreatedAt.Format("2006-01-02.15.04"))
} }
// GetKeychainItemName panics on non-Darwin platforms // GetKeychainItemName returns an error on non-Darwin platforms
func (k *KeychainUnlocker) GetKeychainItemName() (string, error) { func (k *KeychainUnlocker) GetKeychainItemName() (string, error) {
panic("keychain unlockers are only supported on macOS") return "", errKeychainNotSupported
} }
// Remove panics on non-Darwin platforms // Remove returns an error on non-Darwin platforms
func (k *KeychainUnlocker) Remove() error { func (k *KeychainUnlocker) Remove() error {
panic("keychain unlockers are only supported on macOS") return errKeychainNotSupported
} }
// NewKeychainUnlocker panics on non-Darwin platforms // NewKeychainUnlocker creates a stub KeychainUnlocker on non-Darwin platforms.
// The returned instance's methods that require macOS functionality will return errors.
func NewKeychainUnlocker(fs afero.Fs, directory string, metadata UnlockerMetadata) *KeychainUnlocker { func NewKeychainUnlocker(fs afero.Fs, directory string, metadata UnlockerMetadata) *KeychainUnlocker {
panic("keychain unlockers are only supported on macOS") return &KeychainUnlocker{
Directory: directory,
Metadata: metadata,
fs: fs,
}
} }
// CreateKeychainUnlocker panics on non-Darwin platforms // CreateKeychainUnlocker returns an error on non-Darwin platforms
func CreateKeychainUnlocker(fs afero.Fs, stateDir string) (*KeychainUnlocker, error) { func CreateKeychainUnlocker(_ afero.Fs, _ string) (*KeychainUnlocker, error) {
panic("keychain unlockers are only supported on macOS") return nil, errKeychainNotSupported
} }
// getLongTermPrivateKey panics on non-Darwin platforms // getLongTermPrivateKey returns an error on non-Darwin platforms
func getLongTermPrivateKey(fs afero.Fs, vault VaultInterface) (*memguard.LockedBuffer, error) { func getLongTermPrivateKey(_ afero.Fs, _ VaultInterface) (*memguard.LockedBuffer, error) {
panic("keychain unlockers are only supported on macOS") return nil, errKeychainNotSupported
} }