CVE-2026-128082: AutoMapper: Uncontrolled Recursion with Constructor Parameters
Summary MaxDepth, whether set explicitly or applied by default (64) to self-referential type maps, was not enforced when the recursion goes through constructor parameters. Mapping a deeply nested source to a destination built through its constructor, such as a positional record, recurses without bound and throws a StackOverflowException. That exception can't be caught and terminates the process. This bypasses the mitigation for CVE-2026-32933.
Details The type depth used by MaxDepth was incremented only after the destination object was created. Constructor parameters, including child objects of the same type, are mapped while the destination is created, so each level recursed before its parent was counted, and the depth check never tripped.
Affected: - destination types mapped through constructor parameters, including positional records - both an explicit MaxDepth(n) and the default limit of 64 - ConstructUsing that maps recursively through context.Mapper
With MaxDepth(10), a 100-level chain was mapped to all 100 levels. On a 1 MB stack (the Windows default), the process crashed at between 1,000 and 2,000 levels.
PoC The type only has a constructor with positional arguments, and MaxDepth is set to 10:
csharp using AutoMapper;
// Setup configuration - with MaxDepth set var mapper = new MapperConfiguration(cfg => { cfg.CreateMap<CircularClass, CircularClass>().MaxDepth(10); }) .CreateMapper();
// Create a deeply nested object (28,000+ levels) var root = new CircularClass(null); var current = root; for (int i = 0; i < 30000; i++) { current.Next = new CircularClass(null); current = current.Next; }
// STACK OVERFLOW even though the max depth is set var mappedRoot = mapper.Map<CircularClass>(root);
public class CircularClass { public CircularClass(CircularClass? Next) { this.Next = Next; }
public CircularClass? Next { get; set; } }
Impact Any application that maps attacker-influenced, deeply nested data to a destination type built through a constructor, with a recursive member, can be crashed. Setting MaxDepth as recommended for CVE-2026-32933 doesn't protect these mappings.
Patches Fixed in 16.3.0 and 15.1.4. The depth is now counted before the destination is created, so constructor mapping stops at the same depth as property mapping.
Workarounds If the destination type has a parameterless constructor and settable properties, cfg.DisableConstructorMapping() makes AutoMapper map through the properties, where MaxDepth is enforced. Positional records have no workaround other than limiting input depth before mapping, or upgrading.
Credits Reported by @mcambria, who found it while writing a test to confirm their MaxDepth mitigation for CVE-2026-32933.
Related - CVE-2026-32933 (GHSA-rvv3-g6hj-g44x) - GHSA-gpwp-5797-mjff: other paths that bypassed MaxDepth (polymorphic maps, runtime-typed members, dictionary and dynamic sources, recursive type converters), fixed in the same releases.
Other sources
AutoMapper is a convention-based object-object mapper in .NET. Prior to 15.1.4 and from 16.0.0 until 16.3.0, AutoMapper increments type depth only after creating the destination, so recursive mapping performed through constructor parameters occurs before MaxDepth is counted. Destinations built through positional records or other constructors, and recursive ConstructUsing mappings that call context.Mapper, can therefore bypass explicit MaxDepth values and the default limit of 64. Deep attacker-influenced input can throw an uncatchable StackOverflowException and terminate the process. This issue is fixed in versions 15.1.4 and 16.3.0.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
nuget/AutoMapperto a version that resolves this vulnerability.Fixed in 15.1.4 - Upgrade
Upgrade
nuget/AutoMapperto a version that resolves this vulnerability.Fixed in 16.3.0 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 15.1.4 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 16.3.0 - Configuration
For destination types with a parameterless constructor and settable properties, call cfg.DisableConstructorMapping() so mapping uses properties where MaxDepth is enforced.
AutoMapper DisableConstructorMapping = enabled - Compensating control
Limit the input depth before mapping when mapping to positional records or other constructor-built destination types.
Event History
Frequently Asked Questions
Are applications using the default depth setting affected?
Yes. The issue affects self-referential type maps using destination constructor parameters even when MaxDepth is not explicitly configured, because the default limit of 64 is also bypassed.
What mapping pattern is required to trigger the crash?
A deeply nested source must be mapped to a destination that is created through constructor parameters and recurses through child objects of the same type. Positional records and recursive ConstructUsing implementations that call context.Mapper are affected patterns.
Does configuring a lower MaxDepth prevent the issue?
No. Explicit MaxDepth settings are not enforced during recursion through constructor parameters; in the documented example, MaxDepth(10) still mapped a 100-level chain completely.
What is the operational impact if the vulnerable recursion is reached?
The mapping can recurse until it throws StackOverflowException, which cannot be caught and terminates the process. On a 1 MB stack, the documented crash occurred between 1,000 and 2,000 nesting levels.