getsops/sops · critical
Failed to verify data integrity. expected mac %q, got %q
Error message
Failed to verify data integrity. expected mac %q, got %q
What it means
After decrypting the stored MAC, DataWithFormat compares it with a freshly computed MAC over the cleartext. A mismatch means the encrypted data does not match its metadata — the plaintext was tampered with, partially written, or the file was edited outside sops. sops refuses to return the data because integrity cannot be guaranteed.
Source
Thrown at decrypt/decrypt.go:67
cipher := aes.NewCipher()
mac, err := tree.Decrypt(key, cipher)
if err != nil {
return nil, err
}
// Compute the hash of the cleartext tree and compare it with
// the one that was stored in the document. If they match,
// integrity was preserved
originalMac, err := cipher.Decrypt(
tree.Metadata.MessageAuthenticationCode,
key,
tree.Metadata.LastModified.Format(time.RFC3339),
)
if err != nil {
return nil, fmt.Errorf("Failed to decrypt original mac: %w", err)
}
if originalMac != mac {
return nil, fmt.Errorf("Failed to verify data integrity. expected mac %q, got %q", originalMac, mac)
}
return store.EmitPlainFile(tree.Branches)
}
// Data is a helper that takes encrypted data and a format string,
// decrypts the data and returns its cleartext in an []byte.
// The format string can be `json`, `yaml`, `ini`, `dotenv` or `binary`.
// If the format string is empty, binary format is assumed.
func Data(data []byte, format string) (cleartext []byte, err error) {
formatFmt := FormatFromString(format)
return DataWithFormat(data, formatFmt)
}
View on GitHub (pinned to 13442bb981)
Solutions
- Restore the original encrypted file from its source of truth (git, S3 versioning) and decrypt again
- Never edit encrypted sops files by hand — edit plaintext via sops editor mode and re-encrypt
- Re-encrypt the known-good plaintext with sops -e to regenerate consistent metadata if the original is lost
- Rule out transport mangling: download with checksum verification, keep binary-safe transfers, normalize line endings consistently
Example fix
// before (transforming the encrypted bytes in-flight corrupts MAC) processed := strings.ReplaceAll(string(encBytes), "\r\n", "\n") plain, err := decrypt.Data([]byte(processed), "yaml") // after plain, err := decrypt.Data(encBytes, "yaml") // pass bytes untouched
Defensive patterns
Strategy: try-catch
Validate before calling
// detect likely mangling before decryption: mixed line endings or unexpected edits
if bytes.Contains(encBytes, []byte("\r\n")) && bytes.Contains(encBytes, []byte("\n")) {
return errors.New("encrypted input has mixed line endings; likely modified in transit")
} Try / catch
plain, err := decrypt.DataWithFormat(encBytes, formatFmt)
if err != nil {
if strings.Contains(err.Error(), "Failed to verify data integrity") {
return fmt.Errorf("encrypted data does not match its metadata; restore the original file and never edit encrypted files directly: %w", err)
}
return err
} Prevention
- Treat sops-encrypted files as immutable — edit only via sops editor mode
- Avoid any transformation (trims, CRLF conversion, pretty-printing) of encrypted bytes
- Use git merge=ours / re-encrypt workflows to prevent merges of encrypted files
- Verify download integrity (checksums, S3 versioning) before decrypting
When it happens
Trigger: originalMac != mac: manual edits to the encrypted file's data branches, truncation by a partial upload/download, differing newline or encoding transformations between encryption and decryption, or decrypting a file whose metadata belongs to a different version.
Common situations: Pipeline stages that strip whitespace or convert line endings (CRLF/LF) before sops runs; git merge of an encrypted file without re-encrypting; checksum-mismatched S3 download; concatenating sops files or copy-pasting encrypted content through editors.
Related errors
- Failed to decrypt original mac: %w
- Unknown datatype: %s
- Failed to read %q: %w
- Could not initialize AES GCM encryption cipher: %s
- Could not generate random bytes for IV: %s
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/db6ea9d90cd00317.
Report an issue: GitHub.