---
id: "CVE-2026-85783"
kind: "vulnerability"
aliases: ["CVE-2026-85783"]
title: "Crypt::Age for Perl: unbounded recipient stanzas exhaust CPU during decryption"
severity: "medium"
cvss: null
epss: null
exploited: false
status: "open"
category: "package"
products: []
ecosystems: []
tags: ["cpan", "crypt-age", "package", "perl"]
not_affected_if: ["decrypts-only-own-files"]
published_at: "2026-10-20T22:20:05+00:00"
first_seen_at: "2026-10-23T21:57:25+00:00"
updated_at: "2026-10-25T05:04:09+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-85783", "first_seen_at": "2026-10-23T21:57:25+00:00"}]
---

# Crypt::Age for Perl: unbounded recipient stanzas exhaust CPU during decryption

Crypt::Age before 0.004 accepts any number of recipient stanzas in an age file header and runs an X25519 scalar multiplication, HKDF and ChaCha20-Poly1305 open for each stanza against every identity held. An attacker who supplies a crafted encrypted file can drive CPU use up before decryption is rejected, causing denial of service.

_Summary, check and fix written by a model from the sources; labelled as such._

## How to check

- Check the installed Crypt::Age version with `perl -MCrypt::Age -e 'print $Crypt::Age::VERSION'` or `cpanm --info Crypt::Age`
- Find code that calls `decrypt`, `decrypt_file` or `decrypt_filehandle` on files from outside the team

## Fix

- Upgrade Crypt::Age to `0.004` or later
- Until upgraded, only decrypt age files the team itself wrote, or limit input size and run decryption under a CPU time limit

## Timeline

- 2026-10-23T21:57:25+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-85783

## From the sources

Crypt::Age versions before 0.004 for Perl allow CPU exhaustion via an unbounded number of recipient stanzas, each costing an X25519 scalar multiplication in unwrap_file_key.

The header parser accepts any number of recipient stanzas, and unwrap_file_key tries every identity against every X25519 stanza. Each attempt runs a scalar multiplication, an HKDF and a ChaCha20-Poly1305 open. The header MAC cannot be checked first, because its key comes from the file key, which only a successful unwrap produces.

Each stanza is 98 bytes of attacker-chosen header and buys one scalar multiplication per identity held, and the file is rejected only after every one of them has run. A caller reaches this through decrypt, decrypt_file or decrypt_filehandle whenever it decrypts a file it did not write.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
