Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-42793

CVE-2026-42793: Absinthe GraphQL DOS Vulnerability

CVE-2026-42793 is a denial of service flaw in Absinthe GraphQL that allows attackers to exhaust the atom table via malicious SDL documents. This post covers the technical details, affected versions, and mitigation steps.

Published:

CVE-2026-42793 Overview

CVE-2026-42793 is an unauthenticated denial-of-service vulnerability in absinthe-graphql/absinthe, the GraphQL toolkit for Elixir. The flaw resides in the Schema Definition Language (SDL) parsing path, where multiple Blueprint.Draft.convert/2 implementations invoke String.to_atom/1 on attacker-controlled identifiers. Because atoms are never garbage-collected on the BEAM virtual machine, each unique name permanently consumes a slot in the fixed-size atom table. An attacker can submit SDL documents containing enough unique directive, field, type, and argument names to exhaust the default 1,048,576-slot table and crash the Erlang node. The issue is tracked as CWE-770 and affects absinthe from 1.5.0 before 1.10.2.

Critical Impact

Any application that passes attacker-controlled GraphQL SDL to Absinthe's parser — including schema-upload endpoints, federation gateways, and developer tools — can be crashed remotely without authentication.

Affected Products

  • absinthe-graphql/absinthe versions >= 1.5.0 and < 1.10.2
  • Elixir applications exposing GraphQL SDL parsing to untrusted input
  • GraphQL federation gateways ingesting remote SDL via Absinthe

Discovery Timeline

  • 2026-05-08 - CVE-2026-42793 published to NVD
  • 2026-05-13 - Last updated in NVD database

Technical Details for CVE-2026-42793

Vulnerability Analysis

Absinthe parses GraphQL SDL documents into Blueprint structures through a series of phases in its execution pipeline. During the Blueprint conversion phase, multiple Blueprint.Draft.convert/2 clauses for SDL language nodes call String.to_atom/1 on names extracted from the parsed document. These names include directive names, field names, type names, and argument names taken directly from user-supplied input.

On the BEAM virtual machine, atoms are interned in a global table that is not garbage-collected. Once an atom is created, it persists for the lifetime of the node. The default table size is 1,048,576 entries. When the table fills, the runtime aborts with a system_limit error and the entire Erlang node terminates, taking down every service running on it.

Root Cause

The root cause is unbounded resource allocation [CWE-770] triggered by use of String.to_atom/1 on untrusted input. The safer alternative String.to_existing_atom/1 would raise on unknown names, but Absinthe's SDL converters did not restrict atom creation to a known set.

Attack Vector

An unauthenticated remote attacker sends one or more SDL documents containing large numbers of unique identifiers to any endpoint that forwards SDL into Absinthe's parser. Typical exposure points include schema-upload features, federation gateways pulling subgraph SDL, and admin tooling that previews user-supplied schemas. Each unique identifier permanently consumes an atom slot; with sufficient submissions the node aborts.

The upstream fix introduces an ExecutableDefinitions validation phase that runs between parsing and Blueprint conversion, rejecting TypeSystemDefinition and TypeSystemExtension nodes in documents submitted for execution.

elixir
+defmodule Absinthe.Phase.Document.Validation.ExecutableDefinitions do
+  @moduledoc """
+  Implements GraphQL spec §5.1.1 "Executable Definitions": a document
+  submitted for execution must contain only OperationDefinition and
+  FragmentDefinition. Any TypeSystemDefinition or TypeSystemExtension
+  is invalid for execution and is rejected here.
+
+  Runs between Phase.Parse and Phase.Blueprint in the `for_document` pipeline.
+  """
+  use Absinthe.Phase
+
+  alias Absinthe.{Blueprint, Language, Phase}
+
+  @executable_definitions [Language.OperationDefinition, Language.Fragment]
+
+  @spec run(Blueprint.t(), Keyword.t()) :: Phase.result_t()
+  def run(%Blueprint{input: %Language.Document{} = document} = blueprint, options \\ []) do
+    case Enum.reject(document.definitions, &(&1.__struct__ in @executable_definitions)) do
+      [] ->
+        {:ok, blueprint}
+
+      type_definitions ->
+        errors =
+          Enum.map(type_definitions, fn node ->
+            %Phase.Error{
+              phase: __MODULE__,
+              message: "#{label(node)} is not an executable definition",
+              locations: [node.loc]
+            }
+          end)

Source: GitHub Commit dd842b9

Detection Methods for CVE-2026-42793

Indicators of Compromise

  • Erlang VM crash logs containing system_limit errors referencing atom table exhaustion
  • Sudden node restarts on hosts running Absinthe-based GraphQL services with no preceding deployment
  • HTTP requests to GraphQL endpoints containing large SDL payloads with high cardinality of unique identifiers

Detection Strategies

  • Inspect application telemetry for monotonic growth in erlang:system_info(:atom_count) over time
  • Alert when atom usage exceeds a threshold percentage of erlang:system_info(:atom_limit)
  • Log and review POST bodies to GraphQL endpoints that contain type, directive, or extend keywords from untrusted clients

Monitoring Recommendations

  • Export BEAM atom-table metrics to your observability stack and set alerts on rapid increases
  • Monitor request size and identifier cardinality on any endpoint that accepts SDL
  • Correlate node restarts with upstream HTTP request volume to identify exhaustion attempts

How to Mitigate CVE-2026-42793

Immediate Actions Required

  • Upgrade absinthe to version 1.10.2 or later in mix.exs and redeploy all affected services
  • Audit application code paths that call Absinthe.run/3, Absinthe.Schema.Notation, or any SDL parser with user-supplied input
  • Restrict or remove endpoints that allow unauthenticated users to submit SDL documents

Patch Information

The fix is included in absinthe 1.10.2. The patch adds an Absinthe.Phase.Document.Validation.ExecutableDefinitions phase to the for_document pipeline, rejecting type-system definitions and extensions before they reach Blueprint conversion. See the GitHub Security Advisory GHSA-qf4g-9fqq-mmm7 and the CNA advisory for details.

Workarounds

  • Place authentication and authorization in front of any endpoint that forwards SDL to Absinthe
  • Enforce strict request-size limits and reject documents containing TypeSystemDefinition nodes at the application edge
  • Increase the BEAM atom limit only as a stopgap; this raises the bar but does not eliminate the underlying flaw
bash
# Update Absinthe dependency in mix.exs, then fetch and compile
# {:absinthe, "~> 1.10.2"}
mix deps.update absinthe
mix deps.compile absinthe
mix test

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.