VYPR
Unrated severityNVD Advisory· Published Jun 1, 2026

CVE-2026-40961

CVE-2026-40961

Description

Apache Airflow login redirect URL bypass allows attackers to redirect authenticated users from a trusted Airflow domain to an attacker-controlled origin.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Apache Airflow login redirect URL bypass allows attackers to redirect authenticated users from a trusted Airflow domain to an attacker-controlled origin.

Vulnerability

The login redirect route in Apache Airflow fails to properly validate URLs containing triple slashes (///) or backslashes (\). Due to differences between Airflow's server-side validation and JavaScript's WHATWG URL parsing, a URL like ///attacker.com is treated by the browser as a valid absolute URL pointing to https://attacker.com, bypassing the is_safe_url check. This vulnerability affects versions prior to apache-airflow 3.2.2 [1].

Exploitation

An attacker needs to be an authenticated user of the Airflow instance. The attacker crafts a redirect URL containing a next parameter with a malformed host prefix (e.g., ///attacker.com or \attacker.com) and tricks another authenticated user into clicking the crafted link. When the victim's browser processes this URL, it bypasses the server-side is_safe_url validation and redirects to the attacker's origin [1].

Impact

Successful exploitation results in an open redirect, allowing the attacker to redirect victims from a trusted Airflow domain to an attacker-controlled site. This can be used for phishing attacks, credential theft, or other social engineering campaigns, as the initial redirect originates from a legitimate Airflow URL [1].

Mitigation

Users should upgrade to apache-airflow 3.2.2 or later, which rejects URLs with /// or \ patterns [1]. As a defense-in-depth measure, operators can place Airflow behind a reverse proxy that strips off-domain next= query parameters before they reach the login endpoint. No CVE is listed in KEV as of publication date.

AI Insight generated on Jun 1, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

2
555f35576e31

Updates the is_url_safe method to reject urls with /// (#65557)

https://github.com/apache/airflowAritra BasuApr 23, 2026via nvd-ref
2 files changed · +21 0
  • airflow-core/src/airflow/api_fastapi/core_api/security.py+6 0 modified
    @@ -779,6 +779,12 @@ def is_safe_url(target_url: str, request: Request | None = None) -> bool:
             # Can't enforce any security check.
             return True
     
    +    # According to WHATWG for http/https /// is interpreted as // whereas urllib doesnt
    +    # this leads to an inconsistency where python returns a target url with /// as a valid url
    +    # The same thing also happens with \ where under WHATWG \ are translated to /
    +    target_url = unquote(target_url).strip()
    +    if target_url.startswith(("//", "/\\", "\\/", "\\\\")):
    +        return False
         for base_url, parsed_base in parsed_bases:
             parsed_target = urlparse(urljoin(base_url, unquote(target_url)))  # Resolves relative URLs
     
    
  • airflow-core/tests/unit/api_fastapi/core_api/test_security.py+15 0 modified
    @@ -413,6 +413,21 @@ def test_is_safe_url(self, url, expected_is_safe):
             request.base_url = "https://requesting_server_base_url.com/prefix2"
             assert is_safe_url(url, request=request) == expected_is_safe
     
    +    @pytest.mark.parametrize(
    +        ("url", "expected_is_safe"),
    +        [
    +            # Using \ or /// to escape host check
    +            ("///some_netlock.com/prefix", False),
    +            ("\\\\some_netlock.com/prefix", False),
    +            # encoded url
    +            ("%5C%5C%5C%5Csome_netlock.com/prefix", False),
    +        ],
    +    )
    +    def test_is_safe_url_without_prefix(self, url, expected_is_safe):
    +        request = Mock()
    +        request.base_url = "https://requesting_server_base_url.com/"
    +        assert is_safe_url(url, request=request) == expected_is_safe
    +
         @pytest.mark.parametrize(
             ("url", "expected_is_safe"),
             [
    
cde4885818be

Updating release notes for 3.2.2rc3

https://github.com/apache/airflowvatsrahul1001May 26, 2026Fixed in 3.2.2via release-tag
2 files changed · +5 4
  • RELEASE_NOTES.rst+3 2 modified
    @@ -24,7 +24,7 @@
     
     .. towncrier release notes start
     
    -Airflow 3.2.2 (2026-05-27)
    +Airflow 3.2.2 (2026-05-29)
     --------------------------
     
     Significant Changes
    @@ -81,7 +81,8 @@ Significant Changes
     
     Bug Fixes
     ^^^^^^^^^
    -
    +- Fix ``Callback.handle_event`` triggerer crash when OpenTelemetry metrics receive dict typed tag values (#67527) (#67529)
    +- UI: Rewrite ``modulepreload hrefs`` to the api-server static path (#67548) (#67556)
     - Correctly pre-allocate ``external_executor_id`` with multiple executors on PostgreSQL (#67388) (#67458)
     - Return raw import-error stacktrace when a Dag file has no registered Dag (#67465) (#67478)
     - UI: Fix Expand/Collapse All on XComs and Audit Log JSON cells (#67316) (#67361)
    
  • reproducible_build.yaml+2 2 modified
    @@ -1,2 +1,2 @@
    -release-notes-hash: 6407b48d1054fe3ce68c09bf4435d91d
    -source-date-epoch: 1779745327
    +release-notes-hash: 504288db9a9dc13a0db859232fab98d0
    +source-date-epoch: 1779811737
    

Vulnerability mechanics

Root cause

"Inconsistent URL parsing between Python's urlparse and the WHATWG URL standard allows `///` and `\\` prefixes to bypass the `is_safe_url` host check."

Attack vector

An authenticated attacker crafts a login redirect URL containing a `next=` parameter that starts with `///` or `\\` followed by an attacker-controlled hostname (e.g., `///evil.com`). Python's `urlparse` treats this as a relative path, passing the `is_safe_url` check, but a browser's JavaScript URL constructor (per WHATWG) interprets `///` as `//`, resolving the redirect to the attacker's origin [CWE-601]. This allows open redirect from a trusted Airflow domain to an arbitrary external site.

Affected code

The vulnerability resides in the `is_safe_url` function in `airflow-core/src/airflow/api_fastapi/core_api/security.py`. The login redirect route in Apache Airflow used this function to validate the `next=` query parameter, but the check could be bypassed with URLs containing `///` or `\\` prefixes.

What the fix does

The patch adds a check at the top of `is_safe_url` that first URL-decodes and strips the target URL, then rejects any URL starting with `//`, `/\`, `\/`, or `\\` [patch_id=4185423]. This closes the inconsistency between Python's `urlparse` (which treats `///` as a relative path) and the WHATWG URL parser used by browsers (which treats `///` as `//`), preventing the open redirect bypass. New unit tests confirm that `///some_netlock.com/prefix`, `\\\\some_netlock.com/prefix`, and the encoded variant are now correctly rejected.

Preconditions

  • authAttacker must be an authenticated Airflow user with access to the login redirect endpoint.
  • configAttacker must control an external web server to receive the redirected victim.
  • inputThe `next=` query parameter must be accepted and processed by the login redirect route.

Generated on Jun 1, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.