Mar 13, 2026·5 min read·2 visits
A flaw in AutoMapper's handling of self-referential object graphs allows remote attackers to trigger a non-catchable StackOverflowException via deeply nested object inputs, causing an application crash. The issue is resolved in version 16.1.1 by enforcing a default recursion limit of 64.
AutoMapper prior to version 16.1.1 is vulnerable to a Denial of Service (DoS) condition caused by uncontrolled recursion during object mapping. An attacker can supply a deeply nested, self-referential object graph consisting of unique instances to trigger a StackOverflowException, resulting in immediate process termination.
AutoMapper is a convention-based object-object mapper for .NET applications. It automates the process of transforming input models into internal domain objects. Many .NET applications utilize AutoMapper within their API layers to process incoming JSON or XML payloads before routing data to internal business logic.
The vulnerability, identified as GHSA-rvv3-g6hj-g44x, affects the mapping engine's handling of self-referential or cyclic object graphs. When an application accepts untrusted data and maps it to a cyclic domain model, an attacker can supply a maliciously crafted, deeply nested payload to exploit the mapping process.
Versions of AutoMapper prior to 16.1.1 fail to impose a hard recursion limit on distinct object instances during traversal. This uncontrolled recursion leads to stack memory exhaustion. The resulting StackOverflowException terminates the application process immediately, creating a high-severity Denial of Service (DoS) condition.
During mapping execution, AutoMapper performs a depth-first traversal of the object tree. When the engine processes a self-referential type mapping, it recognizes the potential for infinite loops. To mitigate standard cyclic references, AutoMapper automatically enables a PreserveReferences configuration flag.
The PreserveReferences feature functions as an object-identity cache. It tracks the specific memory references of objects currently undergoing mapping. If the engine encounters an object reference it has already processed in the current graph, it returns the cached mapped instance instead of traversing it again, successfully preventing infinite loops on the exact same object.
The vulnerability exists because this identity caching relies strictly on object reference equality. An attacker bypasses this protection by constructing a payload composed of entirely distinct object instances. Since each nested object in the payload occupies a unique memory address, the identity cache never registers a collision. The depth-first traversal continues unabated until the Common Language Runtime (CLR) stack limit is exceeded.
The vulnerable implementation resides in the configuration compilation phase where type maps are processed. The engine enables identity tracking but does not configure an upper bound for structural depth. This leaves the traversal bounded only by available thread stack memory.
The patch introduced in commit 0afaf1e91648fca1a57512e94dd00a76ee016816 resolves the flaw within src/AutoMapper/Execution/TypeMapPlanBuilder.cs. The maintainers modified the CheckForCycles method to enforce a default recursion depth limit for self-referential mappings.
// src/AutoMapper/Execution/TypeMapPlanBuilder.cs (Patched)
private static void CheckForCycles(IGlobalConfiguration configuration, TypeMap typeMap, ...)
{
// Cycle detection logic...
memberTypeMap.PreserveReferences = true;
// Ensure a maximum depth is enforced even for distinct objects
if (memberTypeMap.MaxDepth == 0)
{
memberTypeMap.MaxDepth = 64;
}
}The engine now assigns a default MaxDepth of 64 whenever a cyclic map is detected and no explicit limit is provided. This ensures the engine throws an application-level mapping exception upon reaching depth 64, preserving the stack and preventing process termination.
Exploitation requires the target application to accept unbounded, nested input data and map it to a self-referential type. Common vectors include ASP.NET Core API endpoints utilizing standard deserializers to parse HTTP request bodies before passing the resulting objects to IMapper.Map.
The attacker constructs a JSON document representing a deep linear chain of objects. The payload must nest continuously without triggering the deserializer's own structural depth limits. The official Proof-of-Concept utilizes a class named Circular containing a single Self property, iterating 30,000 times to construct the chain.
// Exploit primitive demonstrating the required structure
var root = new Circular();
var current = root;
for (int i = 0; i < 30_000; i++)
{
current.Self = new Circular();
current = current.Self;
}
// Execution triggers the vulnerability
var result = mapper.Map<Circular>(root);When the application executes the mapping, the thread stack rapidly fills with nested function frames. Because the objects are structurally valid but excessively deep, no validation errors occur prior to stack exhaustion. The process crashes asynchronously relative to the initial request handling.
The primary impact of this vulnerability is a complete Denial of Service. In the .NET CLR, a StackOverflowException is non-recoverable. The runtime deliberately prevents application code from catching this exception using standard try-catch blocks to ensure state consistency.
When the exception occurs, the operating system forcibly terminates the hosting process. In a web server context, this destroys all active requests and drops established connections. Persistent exploitation prevents the application from serving legitimate traffic, as the process will continuously crash and restart upon receiving the payload.
The CVSS v3.1 score is evaluated at 8.7 (High). The attack vector is strictly network-based and requires no authentication or user interaction. Confidentiality and Integrity are not impacted, as the vulnerability does not expose memory or allow arbitrary code execution.
Organizations must upgrade the AutoMapper NuGet package to version 16.1.1 or later to remediate the vulnerability. This version securely defaults all self-referential mappings to a maximum depth of 64, aligning with standard depth limits found in modern JSON serializers.
Developers implementing explicit .PreserveReferences() configurations must manually define a .MaxDepth() parameter. Explicitly instructing AutoMapper to preserve references bypasses the automatic depth assignment applied by the patch. Failure to specify a limit on these mappings will reintroduce the vulnerability.
Applications legitimately requiring object graphs deeper than 64 levels can adjust the threshold using cfg.CreateMap<Node, Node>().MaxDepth(128). Security engineering teams should evaluate whether deep object graphs are strictly necessary and implement corresponding depth limits at the network deserialization layer.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
AutoMapper LuckyPennySoftware | < 16.1.1 | 16.1.1 |
| Attribute | Detail |
|---|---|
| Vulnerability Class | Uncontrolled Recursion |
| CWE ID | CWE-674, CWE-400 |
| CVSS Score | 8.7 |
| Attack Vector | Network / Remote |
| Impact | Denial of Service (Process Termination) |
| Exploit Status | Proof of Concept Available |
The product does not properly control the amount of recursion that takes place, consuming excessive resources, such as allocated memory or the program stack.