JuliusBrussee/caveman · error
ciphertext too short
Error message
ciphertext too short
What it means
Decrypt's local path found the envelope shorter than the GCM nonce size (12 bytes) — there is no nonce to split off, so the ciphertext is truncated, corrupt, or simply not a secretbox envelope. This length guard runs before gcm.Open, which would otherwise panic or misparse.
Source
Thrown at shared/platform/secretbox/secretbox.go:132
if runtimeenv.IsProduction() &&
!strings.EqualFold(strings.TrimSpace(os.Getenv("CAVE_KMS_ALLOW_LEGACY_LOCAL_DECRYPT")), "true") {
return nil, fmt.Errorf("secretbox: production refuses legacy local ciphertext")
}
keyBytes, err := loadKey()
if err != nil {
return nil, err
}
block, err := aes.NewCipher(keyBytes)
if err != nil {
return nil, fmt.Errorf("aes cipher: %w", err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("aes-gcm: %w", err)
}
ns := gcm.NonceSize()
if len(envelope) < ns {
return nil, fmt.Errorf("ciphertext too short")
}
nonce, ct := envelope[:ns], envelope[ns:]
plain, err := gcm.Open(nil, nonce, ct, nil)
if err != nil {
return nil, fmt.Errorf("aes-gcm open: %w", err)
}
return plain, nil
}
// DecryptPayloadKey unwraps an artifact data-encryption key. KMS envelopes are
// restricted to the configured payload key plus the explicit legacy secrets
// key used before key separation.
func DecryptPayloadKey(envelope []byte) ([]byte, error) {
if kms.IsEnvelope(envelope) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
plaintext, err := kms.DecryptPayload(ctx, envelope)
if err != nil {View on GitHub (pinned to 766dce6b13)
Solutions
- Check how the envelope was transported/stored — truncation usually happens in a VARCHAR column, log field, or copy-paste
- Validate envelope length before storing and use bytea/base64 transport end to end
- If the value is actually plaintext or another format, route it through the correct decode path
- Discard unrecoverable fragments; there is no way to decrypt a truncated GCM ciphertext
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at shared/platform/secretbox/secretbox.go:132 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18).
Data as JSON: /api/errors/1fe530d43b22a78f.
Report an issue: GitHub.