From 23cd77d15c1492e38fd12838afa51787fed0fe53 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 25 Jul 2025 14:27:20 +0200 Subject: [PATCH 1/3] Fix Shamir threshold encoding for INI and ENV files. Signed-off-by: Felix Fontein --- stores/flatten.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stores/flatten.go b/stores/flatten.go index 16d730380..1560b20dc 100644 --- a/stores/flatten.go +++ b/stores/flatten.go @@ -274,5 +274,11 @@ func EncodeNonStrings(m map[string]interface{}) { if vInt, ok := v.(int); ok { m["shamir_threshold"] = fmt.Sprintf("%d", vInt) } + // FlattenMetadata serializes the input as JSON and then deserializes it. + // The JSON unserializer treats every number as a float, so the above 'if' + // never applies in that situation. + if vFloat, ok := v.(float64); ok { + m["shamir_threshold"] = fmt.Sprintf("%g", vFloat) + } } } From c30e36ea7650eaccfae7d8031c6b58ce74bec519 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 28 Jul 2025 22:00:48 +0200 Subject: [PATCH 2/3] Store floating point number without decimal places. Co-authored-by: Hidde Beydals Signed-off-by: Felix Fontein --- stores/flatten.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stores/flatten.go b/stores/flatten.go index 1560b20dc..85ad63bc4 100644 --- a/stores/flatten.go +++ b/stores/flatten.go @@ -278,7 +278,7 @@ func EncodeNonStrings(m map[string]interface{}) { // The JSON unserializer treats every number as a float, so the above 'if' // never applies in that situation. if vFloat, ok := v.(float64); ok { - m["shamir_threshold"] = fmt.Sprintf("%g", vFloat) + m["shamir_threshold"] = fmt.Sprintf("%.0f", vFloat) } } } From df09e2c119f1942dc88bcb89124f88975ee87d39 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 28 Jul 2025 22:08:10 +0200 Subject: [PATCH 3/3] Also parse floating point numbers if they represent integers. Signed-off-by: Felix Fontein --- stores/flatten.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/stores/flatten.go b/stores/flatten.go index 85ad63bc4..f961d74d0 100644 --- a/stores/flatten.go +++ b/stores/flatten.go @@ -248,7 +248,14 @@ func DecodeNonStrings(m map[string]interface{}) error { case string: vInt, err := strconv.Atoi(val) if err != nil { - return fmt.Errorf("shamir_threshold is not an integer: %s", err.Error()) + // Older versions of SOPS stored shamir_threshold as a floating point representation + // of the actual integer. Try to parse a floating point number and see whether it + // can be converted without loss to an integer. + vFloat, floatErr := strconv.ParseFloat(val, 64) + vInt = int(vFloat) + if floatErr != nil || float64(vInt) != vFloat { + return fmt.Errorf("shamir_threshold is not an integer: %s", err.Error()) + } } m["shamir_threshold"] = vInt case int: