Skip to content

Commit 5e6aa7f

Browse files
authored
Fix double encryption prevention (#346)
* Fix binary file bug double encryption prevention The `ensureNoMetadata` function was incorrectly implemented and called LoadEncryptedFile on the InputStore and checked whether the returned error was MetadataNotFound or not. In the case where loading the input file as an encrypted file would fail (e.g. due to syntax errors), it would incorrectly report the file as having a "sops" branch. When using the binary mode, it would try to load the file as an encrypted binary file (which is expected to be JSON), which would fail, thus triggering this error. * Add functional test for binary file roundtrip
1 parent 97ce8a6 commit 5e6aa7f

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

cmd/sops/encrypt.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ func (err *fileAlreadyEncryptedError) UserError() string {
4343
return wordwrap.WrapString(message, 75)
4444
}
4545

46-
func ensureNoMetadata(opts encryptOpts, bytes []byte) error {
47-
_, err := opts.InputStore.LoadEncryptedFile(bytes)
48-
if err == sops.MetadataNotFound {
49-
return nil
46+
func ensureNoMetadata(opts encryptOpts, branch sops.TreeBranch) error {
47+
for _, b := range branch {
48+
if b.Key == "sops" {
49+
return &fileAlreadyEncryptedError{}
50+
}
5051
}
51-
return &fileAlreadyEncryptedError{}
52+
return nil
5253
}
5354

5455
func encrypt(opts encryptOpts) (encryptedFile []byte, err error) {
@@ -57,13 +58,13 @@ func encrypt(opts encryptOpts) (encryptedFile []byte, err error) {
5758
if err != nil {
5859
return nil, common.NewExitError(fmt.Sprintf("Error reading file: %s", err), codes.CouldNotReadInputFile)
5960
}
60-
if err := ensureNoMetadata(opts, fileBytes); err != nil {
61-
return nil, common.NewExitError(err, codes.FileAlreadyEncrypted)
62-
}
6361
branch, err := opts.InputStore.LoadPlainFile(fileBytes)
6462
if err != nil {
6563
return nil, common.NewExitError(fmt.Sprintf("Error unmarshalling file: %s", err), codes.CouldNotReadInputFile)
6664
}
65+
if err := ensureNoMetadata(opts, branch); err != nil {
66+
return nil, common.NewExitError(err, codes.FileAlreadyEncrypted)
67+
}
6768
path, err := filepath.Abs(opts.InputPath)
6869
if err != nil {
6970
return nil, err

functional-tests/src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,4 +385,28 @@ b: ba"#
385385
assert_eq!(output.stdout, b"multi\nline");
386386
}
387387

388+
389+
#[test]
390+
fn roundtrip_binary() {
391+
let data = b"\"\"{}this_is_binary_data";
392+
let file_path = prepare_temp_file("test.binary", data);
393+
let output = Command::new(SOPS_BINARY_PATH)
394+
.arg("-i")
395+
.arg("-e")
396+
.arg(file_path.clone())
397+
.output()
398+
.expect("Error running sops");
399+
assert!(output.status.success(),
400+
"SOPS failed to encrypt a binary file");
401+
let output = Command::new(SOPS_BINARY_PATH)
402+
.arg("-d")
403+
.arg(file_path.clone())
404+
.output()
405+
.expect("Error running sops");
406+
assert!(output.status
407+
.success(),
408+
"SOPS failed to decrypt a binary file");
409+
assert_eq!(output.stdout, data);
410+
}
411+
388412
}

0 commit comments

Comments
 (0)