Kanidm: Anonymous stack-overflow crash via nested LDAP filter

An anonymous client can crash the kanidmd process with a single deeply nested LDAP search filter on the LDAPS interface via stack overflow, taking down the web/OIDC API at the same time.

Advisory ID: TP-2026-028
Product: Kanidm (identity and access management)
Vulnerability type: Denial of service through uncontrolled recursion (CWE-674)
CVE: not requested
CVSS 3.1: 7.5 (High) · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Affected versions: <= 1.10.3
Status: Published by the vendor; no fixed version designated
Vendor advisory: GHSA-qcrp-p3rq-pffr
Reported: 11 June 2026

Summary

Kanidm is an identity and access management server. The LDAPS interface decodes every inbound message with the BER parser before any authentication, bind or depth check runs. The recursive-descent decoder has no nesting-depth bound, so a search filter with several thousand nested AND elements consumes one stack frame per level and overflows the worker stack. Because the LDAPS interface and the HTTPS web/OIDC API share the same process, the crash takes down the whole service. turingpoint verified the flow and reported it to the vendor.

Root cause

The LDAPS session decodes every message through FramedRead::new(r, LdapCodec::default()) (server/core/src/ldaps.rs:64); LdapCodec from ldap3_proto 0.7.1 delegates structural parsing to the lber 0.4.2 decoder. That recursive-descent decoder builds the nested tag tree with no depth bound, one stack frame per level. The depth check Filter::from_ldap_ro (server/lib/src/filter.rs:772, DEFAULT_LIMIT_FILTER_DEPTH_MAX) runs only after the codec has already built the full tree, so it never sees the input. The only codec limit is DEFAULT_MAX_BER_SIZE (32 KB), a size bound and not a depth bound, so a payload of about 31.9 KB stays under it and overflows the default 2 MB stack (server/daemon/src/main.rs:730, thread_stack_size commented out). It is an incomplete fix of GHSA-qcxq-75wr-5cm8: ldap3_proto 0.7.1 bounds only the PEG string-filter path, the BER wire path stays unbounded.

Proof of Concept

Schematically (anonymous, LDAPS port):

SearchRequest with a filter that nests several thousand AND elements
(total size just under 32 KB).

-> the recursive BER decode overflows the worker stack and the process aborts
   (SIGSEGV / "stack overflow"); the LDAPS and HTTPS ports are then offline.

The payload stays under the codec's only size bound because that bound does not measure nesting depth; the application's depth check runs after decoding and therefore too late.

Impact

  • Crashes the entire kanidmd process with a single packet.
  • Takes down the LDAPS interface and the HTTPS web/OIDC API at once, since they share one process.
  • Triggerable anonymously once LDAP is enabled; no authentication required.

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.