CVE-2026-82726 Overview
CVE-2026-82726 is a permissive regular expression vulnerability [CWE-178] in the ash_phoenix library from the ash-project ecosystem. The flaw resides in AshPhoenix.Helpers.get_subdomain/2, which interpolates the configured root host into a regular expression without escaping. A remote client can send a crafted Host header to select an arbitrary tenant in an Ash-based Phoenix application or degrade request processing. Case-sensitive comparison also allows uppercase variants of the root host to bypass the allowlist. The issue affects ash_phoenix from version 2.1.26 before 2.3.25.
Critical Impact
Attackers can control tenant selection in multi-tenant Ash applications by sending a manipulated Host header, potentially accessing data belonging to a different tenant.
Affected Products
- ash-project ash_phoenix versions 2.1.26 through 2.3.24
- Multi-tenant Phoenix applications built on the Ash framework using get_subdomain/2
- Elixir/Erlang web applications relying on host-based tenant routing via ash_phoenix
Discovery Timeline
- 2026-08-31 - CVE-2026-82726 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-82726
Vulnerability Analysis
The defect lies in how AshPhoenix.Helpers.get_subdomain/2 extracts a tenant identifier from conn.host. The function stripped the configured root domain using String.replace(host, ~r/.?#{root_host}/, ""). Because root_host is interpolated raw into a regex literal, every . becomes a wildcard and any metacharacter is treated as a pattern. The replacement is global and unanchored, so a match is removed from anywhere in the host string rather than only at the trailing suffix.
With root_host set to example.com, a request bearing Host: foo.exampleXcom.attacker.net produces the tenant value foo.attacker.net. A root_host containing metacharacters or a nil value further degrades matching or raises on every request, creating a denial-of-service condition. The comparison is also case-sensitive, so TENANT.EXAMPLE.COM and EXAMPLE.COM bypass the root-host allowlist. conn.host is derived from the client-supplied Host header, which is fully attacker-controlled.
Root Cause
Unescaped interpolation of user-relevant configuration data into a regular expression, combined with an unanchored global replace and case-sensitive membership checks, produces improper host validation as described in [CWE-178: Improper Handling of Case Sensitivity].
Attack Vector
An unauthenticated remote client sends a crafted HTTP Host header. The vulnerable regex accepts hosts that visually resemble the root domain but do not end with it, or that match with mixed case. The application then treats the residual string as a legitimate tenant subdomain and scopes queries accordingly.
# Vulnerable path (pre-2.3.25) in lib/ash_phoenix/helpers.ex
def get_subdomain(host, endpoint) when is_atom(endpoint) do
root_host = endpoint.config(:url)[:host]
if host in [root_host, "localhost", "127.0.0.1", "0.0.0.0"] do
nil
else
host
|> String.trim_leading("www.")
|> String.replace(~r/.?#{root_host}/, "")
|> case do
"" -> nil
subdomain -> subdomain
end
end
end
# Patched path (2.3.25) matches the root host case-insensitively and only as an exact trailing suffix
defp strip_root_host(host, root_host) when is_binary(host) and is_binary(root_host) do
host = host |> String.downcase() |> String.trim_leading("www.")
root_host = String.downcase(root_host)
cond do
host in [root_host, "localhost", "127.0.0.1", "0.0.0.0"] ->
nil
# ... exact trailing-suffix match logic follows
end
end
Detect Identity Attacks the Moment Authentication Fails
Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.
Stop Identity AttacksDetection Methods for CVE-2026-82726
Indicators of Compromise
- Inbound HTTP requests with Host headers where the root domain is present but not as an exact trailing suffix, for example foo.exampleXcom.attacker.net when the configured root is example.com.
- Requests with Host values that use mixed or uppercase forms of the configured root domain, such as TENANT.EXAMPLE.COM.
- Application error spikes referencing String.replace/3 or regex compilation when root_host contains regex metacharacters or is nil.
Detection Strategies
- Add web-application-firewall or reverse-proxy rules that reject requests whose Host header does not end with an approved root domain using an exact, case-insensitive suffix match.
- Instrument AshPhoenix.Helpers.get_subdomain/2 call sites to log resolved tenant values alongside the raw Host header and compare against the tenant allowlist.
- Review access logs for tenant identifiers that were never provisioned in the application database.
Monitoring Recommendations
- Alert on any HTTP request where the Host header contains the root domain string embedded in the middle rather than as a trailing suffix.
- Track the ratio of 5xx responses correlated with unusual Host header values to detect the denial-of-service variant.
- Retain reverse-proxy and application logs long enough to correlate anomalous tenant access patterns across sessions.
How to Mitigate CVE-2026-82726
Immediate Actions Required
- Upgrade ash_phoenix to version 2.3.25 or later in mix.exs and redeploy affected applications.
- Audit multi-tenant data access logs for tenant identifiers derived from unexpected Host values since the deployment of a vulnerable version.
- Enforce a strict allowlist of accepted Host header values at the reverse proxy or load balancer.
Patch Information
The fix is available in ash_phoenix 2.3.25. Commit 8306f29 replaces the regex-based approach with a case-insensitive, exact trailing-suffix match. Additional detail is available in the GitHub Security Advisory GHSA-rpf8-q9jh-qxrr and the CNA advisory entry.
Workarounds
- If immediate upgrade is not possible, replace calls to AshPhoenix.Helpers.get_subdomain/2 with a local helper that lowercases both inputs and validates an exact trailing-suffix match on the root host.
- Configure the reverse proxy (for example, Nginx or an application load balancer) to normalize Host header casing and reject values that do not match an approved suffix list.
- Ensure the endpoint :url[:host] configuration contains no regular-expression metacharacters and is never nil in production.
# Upgrade ash_phoenix to the patched release
# In mix.exs:
# {:ash_phoenix, "~> 2.3.25"}
mix deps.update ash_phoenix
mix deps.get
mix compile --force
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

