From f6ece99630c910db0aa108e666af879024f641e2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 27 Dec 2023 18:23:27 +0100 Subject: [PATCH] Add check to avoid that UnencryptedCommentRegex matches encrypted comments. Signed-off-by: Felix Fontein --- sops.go | 8 ++++++++ sops_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/sops.go b/sops.go index 798291f3a..4b97292a1 100644 --- a/sops.go +++ b/sops.go @@ -498,6 +498,14 @@ func (tree Tree) Encrypt(key []byte, cipher Cipher) (string, error) { if err != nil { return nil, fmt.Errorf("Could not encrypt value: %s", err) } + if ok && tree.Metadata.UnencryptedCommentRegex != "" { + // If an encrypted comment matches tree.Metadata.UnencryptedCommentRegex, decryption will fail + // as the MAC does not match, and the commented value will not be decrypted. + matched, _ := regexp.Match(tree.Metadata.UnencryptedCommentRegex, []byte(in.(string))) + if matched { + return nil, fmt.Errorf("Encrypted comment %q matches UnencryptedCommentRegex! Make sure that UnencryptedCommentRegex cannot match an encrypted comment.", in) + } + } } return in, nil }) diff --git a/sops_test.go b/sops_test.go index e7f8623f6..4a58f0866 100644 --- a/sops_test.go +++ b/sops_test.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "reflect" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -38,6 +39,23 @@ func (c reverseCipher) Decrypt(value string, key []byte, path string) (plaintext return reverse(value), nil } +type encPrefixCipher struct{} + +func (c encPrefixCipher) Encrypt(value interface{}, key []byte, path string) (string, error) { + b, err := ToBytes(value) + if err != nil { + return "", err + } + return "ENC:" + string(b), nil +} +func (c encPrefixCipher) Decrypt(value string, key []byte, path string) (plaintext interface{}, err error) { + v, ok := strings.CutPrefix(value, "ENC:") + if !ok { + return nil, fmt.Errorf("String not prefixed with 'ENC:'") + } + return v, nil +} + func TestUnencryptedSuffix(t *testing.T) { branches := TreeBranches{ TreeBranch{ @@ -599,6 +617,26 @@ func TestUnencryptedCommentRegex(t *testing.T) { } } +func TestUnencryptedCommentRegexFail(t *testing.T) { + branches := TreeBranches{ + TreeBranch{ + TreeItem{ + Key: Comment{"sops:noenc"}, + Value: nil, + }, + TreeItem{ + Key: "foo", + Value: "bar", + }, + }, + } + tree := Tree{Branches: branches, Metadata: Metadata{UnencryptedCommentRegex: "ENC"}} + cipher := encPrefixCipher{} + _, err := tree.Encrypt(bytes.Repeat([]byte("f"), 32), cipher) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "Encrypted comment \"ENC:sops:noenc\" matches UnencryptedCommentRegex!") +} + type MockCipher struct{} func (m MockCipher) Encrypt(value interface{}, key []byte, path string) (string, error) {