getsops/sops · error

failed to base64 decode Azure Key Vault encrypted key: %w

Error message

failed to base64 decode Azure Key Vault encrypted key: %w

What it means

Raised in DecryptContext when the stored EncryptedKey string cannot be decoded as base64 RawURL encoding (no padding, URL-safe alphabet). The EncryptedKey on the MasterKey is corrupted or was not produced by this library's encoder.

Source

Thrown at azkv/keysource.go:272

//
// Consider using DecryptContext instead.
func (key *MasterKey) Decrypt() ([]byte, error) {
	return key.DecryptContext(context.Background())
}

// DecryptContext decrypts the EncryptedKey field with Azure Key Vault and returns
// the result.
func (key *MasterKey) DecryptContext(ctx context.Context) ([]byte, error) {
	token, err := key.getTokenCredential()
	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Decryption failed")
		return nil, fmt.Errorf("failed to get Azure token credential to decrypt: %w", err)
	}

	rawEncryptedKey, err := base64.RawURLEncoding.DecodeString(key.EncryptedKey)
	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Decryption failed")
		return nil, fmt.Errorf("failed to base64 decode Azure Key Vault encrypted key: %w", err)
	}

	c, err := azkeys.NewClient(key.VaultURL, token, key.clientOptions)
	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Decryption failed")
		return nil, fmt.Errorf("failed to construct Azure Key Vault client to decrypt data: %w", err)
	}

	resp, err := c.Decrypt(ctx, key.Name, key.Version, azkeys.KeyOperationParameters{
		Algorithm: to.Ptr(azkeys.EncryptionAlgorithmRSAOAEP256),
		Value:     rawEncryptedKey,
	}, nil)
	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Decryption failed")
		return nil, fmt.Errorf("failed to decrypt sops data key with Azure Key Vault key '%s': %w", key.ToString(), err)
	}
	log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Decryption succeeded")
	return resp.KeyOperationResult.Result, nil

View on GitHub (pinned to 13442bb981)

Solutions

  1. Re-encrypt the file with `sops -e` using a valid Azure KV key to regenerate a clean EncryptedKey
  2. Restore the original encrypted key blob from git history or backup
  3. Check for trailing whitespace/newlines or '=' padding in the EncryptedKey field and remove/fix them
  4. Verify the value is URL-safe base64 (no '+' or '/' characters)

Example fix

// before
enc := "a+b/c=="  // standard base64, fails RawURL decode
// after
enc := "a-b_c"    // raw URL-safe base64 as produced by sops
Defensive patterns

Strategy: validation

Validate before calling

func isValidRawURLBase64(s string) bool {
	_, err := base64.RawURLEncoding.DecodeString(strings.TrimSpace(s))
	return err == nil
}
// before decrypt: if !isValidRawURLBaseKey(masterKey.EncryptedKey) { re-encrypt from a backup }

Type guard

func validEncryptedKey(s string) bool {
	if s == "" || strings.ContainsAny(s, "+/ =") { return false }
	_, err := base64.RawURLEncoding.DecodeString(s)
	return err == nil
}

Try / catch

if _, err := base64.RawURLEncoding.DecodeString(key.EncryptedKey); err != nil {
	// recover the original .sops.yaml from git: git checkout HEAD^ -- .sops.yaml
	return fmt.Errorf("corrupted azure kv encrypted key, restore from git history: %w", err)
}

Prevention

When it happens

Trigger: Calling Decrypt on an Azure KV MasterKey whose EncryptedKey was hand-edited, truncated, copied with standard-base64 '+'/'/' characters, contains whitespace/padding '=' characters, or was written by a different tooling version.

Common situations: Manually editing .sops.yaml and mangling the azure-vault encrypted key blob, copy-pasting the key through something that line-wrapped or re-encoded it, git merge conflicts partially resolved.

Related errors


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/1fa94e6d376db1ac. Report an issue: GitHub.