1. Executive summary
Apache Airflow's serialization layer reconstructs exception nodes by calling import_string() on a class name taken from a serialized blob and instantiating it with arguments from the same blob, with no restriction on what can be imported. A Dag author can place a value in an operator's executor_config that causes an arbitrary callable to be imported and invoked, and the code runs in the Scheduler on its normal reconstruction loop and in the API server on any authenticated Dag read such as GET /api/v2/dags/{dag_id}/details. Both components hold the metadata database credentials and the JWT signing secret, and the Airflow security model states neither should ever execute Dag-author code. No non-default configuration is required. This is a different sink from CVE-2026-33264, which covered only the trigger branch of the same deserializer, so deployments that upgraded in response to that advisory remain affected through the exception branch and must upgrade again to apache-airflow 3.3.1 or later.
2. Regulatory framing
| Article | Trigger (the fact in this item) | Practical impact |
|---|---|---|
| DORA Art. 17 | The flaw executes Dag-author code inside the Scheduler and API server, the two components holding the metadata database credentials and the JWT signing secret, so an exploited instance is an ICT-related incident requiring a managed response process. | Clients running Airflow in a DORA scope must be able to detect, contain and recover from Scheduler or API-server compromise, not only patch the package. |
| DORA Art. 28 | Airflow is an ICT third-party dependency whose compromise reaches the metadata database and JWT signing secret, which are the trust anchors for the rest of the deployment. | Third-party risk records for Airflow must reflect that a single package upgrade closes an execution path in two privileged components. |
| NIS2 Art. 21(2)(d) | The vulnerability is in a software component obtained through the supply chain, and the fix is a version upgrade to apache-airflow 3.3.1 or later. | Supply chain security measures must include tracking this advisory and verifying the upgrade across all Airflow deployments. |
3. Technical analysis & attack chain
The vulnerability is a deserialization flaw in Airflow's serialization layer, classified CWE-502 (Deserialization of Untrusted Data). The exception-node reconstruction path calls import_string() on a class name read from the serialized blob and instantiates it with arguments from the same blob, with no allowlist on the imported class. An operator's executor_config reaches that branch, so a Dag author controls the class name and arguments that the deserializer imports and invokes.
Confirmed attack chain:
- A Dag author places a value in an operator's
executor_configthat names an arbitrary callable and its arguments. - The value is serialized into the Dag blob as part of normal Dag processing.
- The Scheduler reconstructs the serialized Dag in its normal loop, with no request involved, and reaches the exception-node branch.
- The deserializer calls
import_string()on the attacker-supplied class name and instantiates it with the attacker-supplied arguments, importing and invoking an arbitrary callable such assubprocess.check_output, orbuiltins.evalon thebuiltins-prefixed variant. - The same reconstruction occurs in the API server on any authenticated read of the Dag, for example
GET /api/v2/dags/{dag_id}/details. - Code executes in the Scheduler and API server contexts, both of which hold the metadata database credentials and the JWT signing secret.
No non-default configuration is required for any of these steps. The execution does not depend on a request reaching the Scheduler; the Scheduler triggers it on its own reconstruction loop, which means an affected deployment can execute the payload without any external interaction once the Dag is present.
The affected components are the Scheduler and the API server. The Airflow security model states that neither should execute Dag-author code, so this is a boundary violation as well as a code-execution flaw. The metadata database credentials and the JWT signing secret are both reachable from the executing context, which makes the impact of a successful trigger broader than the Airflow process itself.
This is a different sink from CVE-2026-33264, which covered only the trigger branch of the same deserializer. Deployments that upgraded in response to the CVE-2026-33264 advisory are still affected through the exception branch and must upgrade again. The fix in apache-airflow 3.3.1 restricts the imported class to a subclass of BaseException.
Discrepancy note: the verified reference data records CVE-2026-33264 at CVSS 9.8 CRITICAL with CWE-502, and the source describes this item as a different sink from that CVE. The source does not provide a CVSS score or CWE for the exception-branch issue itself, so no severity is assigned to it here beyond the CWE-502 classification carried by the deserialization mechanism.
4. Mitigation & containment
P1 (within 24h):
- Upgrade apache-airflow to 3.3.1 or later on every deployment, including Scheduler and API server instances. This is the vendor fix and it closes the exception branch by restricting the imported class to a subclass of
BaseException. - If an immediate upgrade is not possible, restrict who can author or modify Dags and who can write to
executor_config, and treat any Dag author as holding code-execution capability in the Scheduler and API server. - Rotate the Airflow metadata database credentials and the JWT signing secret on any deployment where a Dag author is not fully trusted, because both are reachable from the executing context.
P2 (within 72h):
- Audit Dag definitions for
executor_configvalues that reference callables outside the expected operator set, and for anybuiltins-prefixed orsubprocess-prefixed values. - Review API server access logs for authenticated reads of
GET /api/v2/dags/{dag_id}/detailsfrom accounts that do not normally read Dag details.
P3 (within 7 days):
- Confirm the upgrade across all environments, including any deployment that was patched for CVE-2026-33264, since that patch does not cover the exception branch.
- Add the Airflow version check to the software inventory so future advisories against the serialization layer are matched against the deployed version.
5. Indicators of compromise
No indicators of compromise available in the source material.
The source describes observable behaviours rather than atomic indicators. The table below lists the behaviours a defender can look for.
Behavioural indicators
| behaviour | where to observe | confidence |
|---|---|---|
Scheduler reconstructs a serialized Dag and imports a class named in executor_config that is not a BaseException subclass |
Scheduler process logs and process execution telemetry on the Scheduler host | high, from the source description of the vulnerable path |
API server imports a class named in a serialized Dag on an authenticated read of GET /api/v2/dags/{dag_id}/details |
API server logs and process execution telemetry on the API server host | high, from the source description of the vulnerable path |
executor_config values referencing subprocess.check_output or builtins.eval |
Dag definition files and the serialized Dag store | medium, these are the examples the source gives, not an exhaustive list |
6. Detection
The source gives distinctive artefacts for the vulnerable path: the import_string() call on a class name from the serialized blob, the executor_config field, and the example callables subprocess.check_output and builtins.eval. These are artefacts of the vulnerable code path and the example payloads, so a string-based rule can match them.
rule Apache_Airflow_Exception_Node_Deserialization
{
meta:
author = "Adverse Trace"
date = "2026-10-03"
reference = "https://github.com/advisories/GHSA-8prw-8m6x-8w6f"
description = "Detects strings associated with the Airflow exception-node deserialization path and its example payloads"
strings:
$import_string = "import_string" ascii
$executor_config = "executor_config" ascii
$subprocess_check_output = "subprocess.check_output" ascii
$builtins_eval = "builtins.eval" ascii
$base_exception = "BaseException" ascii
condition:
uint32(0) != 0x04034b50 and
(
($import_string and $executor_config) or
$subprocess_check_output or
$builtins_eval
)
}
title: Airflow exception-node deserialization callable import
id: 8f3c2a91-4d7e-4b1a-9c2e-6a5f0d3b7e21
status: experimental
description: Detects Scheduler or API server processes importing a callable named in a serialized Dag executor_config, consistent with the Airflow exception-node deserialization path.
author: Adverse Trace
date: 2026-10-03
references:
- https://github.com/advisories/GHSA-8prw-8m6x-8w6f
logsource:
category: process_creation
product: linux
detection:
selection_airflow:
Image|endswith:
- '/airflow'
- '/airflow-scheduler'
- '/airflow-api-server'
selection_callable:
CommandLine|contains:
- 'subprocess.check_output'
- 'builtins.eval'
condition: selection_airflow and selection_callable
falsepositives:
- Legitimate Dag definitions that reference these callables in executor_config
level: high
CVE assessment
1 referenced CVE — 1 critical (CVSS ≥ 9.0)
| CVE | CVSS | Exploited | EPSS | Summary |
|---|---|---|---|---|
| CVE-2026-33264 | 9.8 Critical | — | 2% | A bug in BaseSerialization.deserialize() allowed unrestricted import_string() of attacker-controlled class paths when the S… |
7. Sources
- GitHub Advisory Database, "Apache Airflow exception-node deserialization permits arbitrary callable execution", https://github.com/advisories/GHSA-8prw-8m6x-8w6f, published 2026-08-12
- NVD, CVE-2026-58076, https://nvd.nist.gov/vuln/detail/CVE-2026-58076
- Apache Airflow pull request 68511, https://github.com/apache/airflow/pull/68511
- Apache Airflow mailing list thread, https://lists.apache.org/thread/t81p688t15jozxsng8521o60nh2kfsos
- Apache Airflow release 3.3.1, https://github.com/apache/airflow/releases/tag/3.3.1
- PyPA advisory database, PYSEC-2026-3991, https://github.com/pypa/advisory-database/tree/main/vulns/apache-airflow/PYSEC-2026-3991.yaml
8. Adverse Trace position
Adverse Trace assesses this as a high-priority upgrade for any client running Apache Airflow, because the vulnerable path executes in the Scheduler without any external request and in the API server on an authenticated read, and both components hold the metadata database credentials and the JWT signing secret. The verified reference data records CVE-2026-33264 at CVSS 9.8 CRITICAL with CWE-502 and not in CISA KEV, and this item is a different sink in the same deserializer, so clients that patched for CVE-2026-33264 are not covered and must upgrade to apache-airflow 3.3.1 or later. The source does not provide a CVSS score for the exception-branch issue, so we do not assign one; the CWE-502 classification and the execution context are the basis for the priority. The example callables in the source are illustrative, not an exhaustive list of what can be imported, so detection should not rely on those strings alone. We will track the Apache Airflow 3.3.1 release and any follow-up advisories against the serialization layer, and we will update this advisory if a CVSS score or exploitation state is published for the exception-branch issue.
Published via PulseTrace — Adverse Trace threat intelligence.