CVE-2026-82752 Overview
CVE-2026-82752 is an Improper Validation of Specified Quantity in Input vulnerability [CWE-1284] affecting the ash-project/ash Elixir framework. The flaw allows an attacker to store values of arbitrary size in string attributes that should be bounded by a length constraint. Ash measures string length using Elixir's String.length/1, which counts Unicode graphemes. A single grapheme can carry an unbounded number of combining marks, so a value satisfying max_length: 2 can still occupy megabytes of storage. The issue affects ash from version 0.10.0 before 3.33.0.
Critical Impact
An unauthenticated attacker can bypass declared string length limits and write arbitrarily large payloads into attributes backed by ETS, Mnesia, or unbounded Postgres text columns, causing unbounded storage growth.
Affected Products
- ash-project/ash versions >= 0.10.0, < 3.33.0
- Applications using Ash.Type.String with max_length or min_length constraints
- Ash resources using Ash.Resource.Validation.StringLength or the string_length expression function
Discovery Timeline
- 2026-09-05 - CVE-2026-82752 published to NVD
- 2026-09-08 - Last updated in NVD database
Technical Details for CVE-2026-82752
Vulnerability Analysis
The vulnerability originates in how Ash counts characters when enforcing string length constraints. The apply_constraints/2 function in lib/ash/type/string.ex, the Ash.Resource.Validation.StringLength validator, and the string_length expression function all delegate to Elixir's String.length/1. That function counts Unicode graphemes rather than codepoints or bytes.
A grapheme is a user-perceived character that may include a base character followed by any number of combining marks. Because the combining-mark count is unbounded, a single grapheme can occupy megabytes. An attribute declared with max_length: 2 will therefore accept a payload consisting of one base character followed by a million combining acute accents.
A secondary integrity issue exists because the counting unit disagrees with common data layers. Postgres counts codepoints when enforcing varchar(n), so values accepted by Ash constraints may be rejected or silently truncated at the storage layer, producing inconsistent state.
Root Cause
The root cause is the use of grapheme counting as a security boundary. Length constraints intended to bound input size do not bound the underlying byte or codepoint count. Where the data layer imposes no independent limit — ETS, Mnesia, or a Postgres text column — the entire value is persisted.
Attack Vector
An attacker submits a request containing a string attribute whose value is a small number of graphemes constructed from many combining codepoints. The constraint check passes. The oversized value is written to the underlying store, letting the attacker grow storage without bound and, on affected data layers, cause resource exhaustion.
# Patch: config/config.exs
config :ash, :read_action_after_action_hooks_in_order?, true
config :ash, :bulk_actions_default_to_errors?, true
config :ash, :redact_sensitive_values_in_errors?, true
+config :ash, :default_string_length_count, :codepoints
config :crux, :sat_testing, true
config :ash, :no_join_mnesia_ets, :dynamic
Source: GitHub Commit a64cab49
Detection Methods for CVE-2026-82752
Indicators of Compromise
- Database rows where a string attribute declared with a small max_length contains values whose byte_size/1 or codepoint count vastly exceeds that limit.
- Unexpected growth of Postgres text, ETS, or Mnesia tables backing Ash resources without a corresponding increase in row count.
- Application logs showing data-layer truncation or rejection errors for values that passed Ash validation.
Detection Strategies
- Audit Ash resources for Ash.Type.String attributes using max_length and inspect stored values with byte_size/1 to identify entries that exceed a reasonable byte budget.
- Query the underlying store directly to compare declared constraint size against actual persisted length in codepoints or bytes.
- Instrument request handlers to log payload sizes for endpoints that write to constrained string attributes.
Monitoring Recommendations
- Track table and column storage growth rates for Ash-managed resources and alert on anomalous increases.
- Monitor request body sizes against declared attribute limits at the ingress or reverse proxy layer.
- Alert on repeated data-layer truncation warnings, which indicate the mismatch between grapheme and codepoint counting is being triggered.
How to Mitigate CVE-2026-82752
Immediate Actions Required
- Upgrade ash to version 3.33.0 or later, which changes the default counting unit for string length constraints.
- Set config :ash, :default_string_length_count, :codepoints (or :bytes) in application configuration to enforce a bounded counting unit.
- Enforce request body size limits at the HTTP layer to cap payload size before values reach Ash validation.
- Where possible, back constrained string attributes with Postgres varchar(n) columns, which independently bound the stored value.
Patch Information
The fix ships in ash3.33.0. It introduces a :default_string_length_count configuration key with values of :codepoints, :bytes, or :graphemes, and updates Ash.Query.Function.StringLength to accept an explicit unit argument. See the GitHub Security Advisory GHSA-cwjv-574p-59f6 and the fix commits a64cab49 and cdbf4c4d.
# Patch: lib/ash/query/function/string_length.ex
defmodule Ash.Query.Function.StringLength do
@moduledoc """
- Trims whitespace from a string
+ Returns the length of a string.
+
+ Without a unit argument, the length is counted in codepoints, unless the
+ backwards-compatibility key `config :ash, :default_string_length_count` is set to
+ `:mixed`, in which case it is counted in graphemes.
+
+ - `:graphemes` - counts unicode graphemes, i.e `String.length/1`.
+ - `:codepoints` - counts unicode codepoints. This matches how most SQL data layers
+ count the length of a string.
+ - `:bytes` - counts bytes, i.e `byte_size/1`.
+
+ A single grapheme may be made up of an unbounded number of codepoints, so counting
+ graphemes places no effective bound on the size of a value. Use `:codepoints` or
+ `:bytes` when the length is being used as a limit.
"""
Source: GitHub Commit cdbf4c4d
Workarounds
- If upgrading immediately is not possible, add custom validations that check byte_size/1 on constrained string attributes and reject oversized values.
- Migrate affected Postgres columns from text to varchar(n) so the database enforces an independent codepoint bound.
- Apply reverse-proxy or web server request size limits sized to the smallest reasonable value for each endpoint writing constrained attributes.
# Update mix.exs to the patched version and fetch dependencies
# {:ash, "~> 3.33.0"}
mix deps.update ash
mix deps.get
# Add to config/config.exs to enforce codepoint counting
# config :ash, :default_string_length_count, :codepoints
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

