{"record":{"id":"fbd5111d25ccdaab","repo":"golang/go","slug":"invalid-length","errorCode":null,"errorMessage":"invalid length","messagePattern":"invalid length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/hpke/hpke.go","lineNumber":199,"sourceCode":"// and then encrypts the provided plaintext like [Sender.Seal] (with no aad).\n// Seal returns the concatenation of the encapsulated key and the ciphertext.\nfunc Seal(pk PublicKey, kdf KDF, aead AEAD, info, plaintext []byte) ([]byte, error) {\n\tenc, s, err := NewSender(pk, kdf, aead, info)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tct, err := s.Seal(nil, plaintext)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn append(enc, ct...), nil\n}\n\n// Export produces a secret value derived from the shared key between sender and\n// recipient. length must be at most 65,535.\nfunc (s *Sender) Export(exporterContext string, length int) ([]byte, error) {\n\tif length < 0 || length > 0xFFFF {\n\t\treturn nil, errors.New(\"invalid length\")\n\t}\n\treturn s.export(exporterContext, uint16(length))\n}\n\n// Open decrypts the provided ciphertext, optionally binding to the additional\n// public data aad, or returns an error if decryption fails.\n//\n// Open uses incrementing counters for each successful call, and must be called\n// in the same order as Seal on the sending side.\nfunc (r *Recipient) Open(aad, ciphertext []byte) ([]byte, error) {\n\tif r.aead == nil {\n\t\treturn nil, errors.New(\"export-only instantiation\")\n\t}\n\tplaintext, err := r.aead.Open(nil, r.nextNonce(), ciphertext, aad)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tr.seqNum++","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/hpke/hpke.go#L181-L217","documentation":"Sender.Export validates the requested output length against RFC 9180 §5.3, which limits the exporter output to a uint16 (0..65535 bytes). A negative length or any value above 0xFFFF is rejected before the KDF expand call.","triggerScenarios":"Calling (*Sender).Export(exporterContext, length) with length < 0 or length > 0xFFFF (65535). Common when length is computed from a larger type (int) and the caller forgets the 16-bit cap.","commonSituations":"Deriving an oversized session key (e.g. asking for 128 KiB), passing -1 as a sentinel, or arithmetic that overflows int but is signed.","solutions":["Clamp length to the [0, 65535] range before calling Export.","Use a smaller, standard key size (16/32/64 bytes) for the derived secret.","If you need more material, call Export multiple times with distinct exporterContext labels and concatenate."],"exampleFix":"// before\nsecret, err := s.Export(\"label\", 1<<20) // > 65535 -> error\n\n// after\nconst maxLen = 0xFFFF\nif length < 0 || length > maxLen {\n    return fmt.Errorf(\"export length %d out of range\", length)\n}\nsecret, err := s.Export(\"label\", length)","handlingStrategy":"validation","validationCode":"const maxExporterLen = 0xFFFF\nfunc export(s *hpke.Sender, label string, n int) ([]byte, error) {\n    if n < 0 || n > maxExporterLen {\n        return nil, fmt.Errorf(\"export length %d out of range [0,%d]\", n, maxExporterLen)\n    }\n    return s.Export(label, n)\n}","typeGuard":null,"tryCatchPattern":"secret, err := s.Export(label, n)\nif err != nil {\n    if err.Error() == \"invalid length\" {\n        // clamp and retry with a safe default, or surface to caller\n        return s.Export(label, min(n, 0xFFFF))\n    }\n    return nil, err\n}","preventionTips":["Use named constants for key sizes (e.g. const aesKeyLen = 32) instead of literals.","Wrap Export in a helper that enforces the uint16 range once.","Prefer deriving multiple shorter secrets over one oversized one."],"tags":["hpke","cryptography","validation","go"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}