VYPR
Medium severity4.3NVD Advisory· Published Apr 24, 2026· Updated Apr 27, 2026

CVE-2026-38743

CVE-2026-38743

Description

The authenticated /ui/dags endpoint did not enforce per-DAG access control on embedded Human-in-the-Loop (HITL) and TaskInstance records: a logged-in Airflow user with read access to at least one DAG could retrieve HITL prompts (including their request parameters) and full TaskInstance details for DAGs outside their authorized scope. Because HITL prompts and TaskInstance fields routinely carry operator parameters and free-form context attached to a task, the leak widens visibility of DAG-run data beyond the intended per-DAG RBAC boundary for every authenticated user.

Users are recommended to upgrade to version 3.2.1 , which fixes this issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
apache-airflowPyPI
< 3.2.1rc13.2.1rc1

Affected products

1
  • cpe:2.3:a:apache:airflow:*:*:*:*:*:*:*:*
    Range: <3.2.1

Patches

1
fed4921098d5

Fix: add RUN, HITL_DETAIL, TASK_INSTANCE entities to /dags endpoint as it returns nested entities in response (#64822)

https://github.com/apache/airflowKevin YangApr 14, 2026via ghsa
3 files changed · +29 0
  • airflow-core/newsfragments/64822.significant.rst+1 0 added
    @@ -0,0 +1 @@
    +Users who only have read access to DAGs will no longer be able to fetch data from the ``/dags`` endpoint, as it now requires additional permissions (``DagAccessEntity.RUN``, ``DagAccessEntity.HITL_DETAIL``, and ``DagAccessEntity.TASK_INSTANCE``). This change was made because the endpoint returns aggregated data from these multiple entities. Please update your custom user roles to include read access for DAG Runs, Task Instances, and HITL Details if those users should still have access to the ``/dags`` endpoint.
    
  • airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dags.py+3 0 modified
    @@ -79,6 +79,9 @@
         response_model_exclude_none=True,
         dependencies=[
             Depends(requires_access_dag(method="GET")),
    +        Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.RUN)),
    +        Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.HITL_DETAIL)),
    +        Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.TASK_INSTANCE)),
         ],
         operation_id="get_dags_ui",
     )
    
  • airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_dags.py+25 0 modified
    @@ -24,6 +24,8 @@
     from fastapi.testclient import TestClient
     from sqlalchemy.orm import Session
     
    +from airflow.api_fastapi.auth.managers.models.resource_details import DagAccessEntity
    +from airflow.api_fastapi.auth.managers.simple.simple_auth_manager import SimpleAuthManager
     from airflow.models import DagRun
     from airflow.models.dag import DagModel, DagTag
     from airflow.models.dag_favorite import DagFavorite
    @@ -235,6 +237,29 @@ def test_should_response_403(self, unauthorized_test_client):
             response = unauthorized_test_client.get("/dags", params={})
             assert response.status_code == 403
     
    +    @pytest.mark.parametrize(
    +        "denied_entity",
    +        [
    +            DagAccessEntity.RUN,
    +            DagAccessEntity.HITL_DETAIL,
    +            DagAccessEntity.TASK_INSTANCE,
    +        ],
    +    )
    +    def test_should_response_403_on_missing_entity_permission(self, test_client, denied_entity):
    +        """Users lacking any sub-entity permission should receive 403 on the DAG list."""
    +        original_is_authorized = SimpleAuthManager.is_authorized_dag
    +
    +        def restricted_is_authorized_dag(self, *, method, user, access_entity=None, details=None):
    +            if access_entity == denied_entity:
    +                return False
    +            return original_is_authorized(
    +                self, method=method, user=user, access_entity=access_entity, details=details
    +            )
    +
    +        with mock.patch.object(SimpleAuthManager, "is_authorized_dag", restricted_is_authorized_dag):
    +            response = test_client.get("/dags")
    +        assert response.status_code == 403
    +
         def test_get_dags_no_n_plus_one_queries(self, session, test_client):
             """Test that fetching DAGs with tags doesn't trigger n+1 queries."""
             num_dags = 5
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.