Skip to content

Commit 0837a42

Browse files
authored
Merge pull request #1372 from fluxcd/redact-values
Fix secret value showing up in logs
2 parents 444b8d2 + a7e4927 commit 0837a42

File tree

2 files changed

+85
-3
lines changed

2 files changed

+85
-3
lines changed

internal/decryptor/decryptor.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func (d *Decryptor) SopsDecryptWithFormat(data []byte, inputFormat, outputFormat
292292
}
293293

294294
cipher := aes.NewCipher()
295-
mac, err := tree.Decrypt(metadataKey, cipher)
295+
mac, err := safeDecrypt(tree.Decrypt(metadataKey, cipher))
296296
if err != nil {
297297
return nil, sopsUserErr("error decrypting sops tree", err)
298298
}
@@ -302,11 +302,11 @@ func (d *Decryptor) SopsDecryptWithFormat(data []byte, inputFormat, outputFormat
302302
// the one that was stored in the document. If they match,
303303
// integrity was preserved
304304
// Ref: github.com/getsops/sops/v3/decrypt/decrypt.go
305-
originalMac, err := cipher.Decrypt(
305+
originalMac, err := safeDecrypt(cipher.Decrypt(
306306
tree.Metadata.MessageAuthenticationCode,
307307
metadataKey,
308308
tree.Metadata.LastModified.Format(time.RFC3339),
309-
)
309+
))
310310
if err != nil {
311311
return nil, sopsUserErr("failed to verify sops data integrity", err)
312312
}
@@ -811,3 +811,33 @@ func detectFormatFromMarkerBytes(b []byte) formats.Format {
811811
}
812812
return unsupportedFormat
813813
}
814+
815+
// safeDecrypt redacts secret values in sops error messages.
816+
func safeDecrypt[T any](mac T, err error) (T, error) {
817+
const (
818+
prefix = "Input string "
819+
suffix = " does not match sops' data format"
820+
)
821+
822+
if err == nil {
823+
return mac, nil
824+
}
825+
826+
var buf strings.Builder
827+
828+
e := err.Error()
829+
prefIdx := strings.Index(e, prefix)
830+
suffIdx := strings.Index(e, suffix)
831+
832+
var zero T
833+
if prefIdx == -1 || suffIdx == -1 {
834+
return zero, err
835+
}
836+
837+
buf.WriteString(e[:prefIdx])
838+
buf.WriteString(prefix)
839+
buf.WriteString("<redacted>")
840+
buf.WriteString(suffix)
841+
842+
return zero, errors.New(buf.String())
843+
}

internal/decryptor/decryptor_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"bytes"
2121
"context"
2222
"encoding/base64"
23+
"errors"
2324
"fmt"
2425
"io/fs"
2526
"os"
@@ -1598,3 +1599,54 @@ func TestDecryptor_detectFormatFromMarkerBytes(t *testing.T) {
15981599
})
15991600
}
16001601
}
1602+
1603+
func TestSafeDecrypt(t *testing.T) {
1604+
for _, tt := range []struct {
1605+
name string
1606+
mac string
1607+
err string
1608+
expectedMac string
1609+
expectedErr string
1610+
}{
1611+
{
1612+
name: "no error",
1613+
mac: "some mac",
1614+
expectedMac: "some mac",
1615+
},
1616+
{
1617+
name: "only prefix",
1618+
err: "Input string was not in a correct format",
1619+
expectedErr: "Input string was not in a correct format",
1620+
},
1621+
{
1622+
name: "only suffix",
1623+
err: "The value does not match sops' data format",
1624+
expectedErr: "The value does not match sops' data format",
1625+
},
1626+
{
1627+
name: "redacted value",
1628+
err: "Input string 1234567897 does not match sops' data format",
1629+
expectedErr: "Input string <redacted> does not match sops' data format",
1630+
},
1631+
} {
1632+
t.Run(tt.name, func(t *testing.T) {
1633+
g := NewWithT(t)
1634+
1635+
var err error
1636+
if tt.err != "" {
1637+
err = errors.New(tt.err)
1638+
}
1639+
1640+
mac, err := safeDecrypt(tt.mac, err)
1641+
1642+
g.Expect(mac).To(Equal(tt.expectedMac))
1643+
1644+
if tt.expectedErr == "" {
1645+
g.Expect(err).To(Not(HaveOccurred()))
1646+
} else {
1647+
g.Expect(err).To(HaveOccurred())
1648+
g.Expect(err.Error()).To(Equal(tt.expectedErr))
1649+
}
1650+
})
1651+
}
1652+
}

0 commit comments

Comments
 (0)