CVE-2020-17515
Description
The "origin" parameter passed to some of the endpoints like '/trigger' was vulnerable to XSS exploit. This issue affects Apache Airflow versions prior to 1.10.13. This is same as CVE-2020-13944 but the implemented fix in Airflow 1.10.13 did not fix the issue completely.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Apache Airflow prior to 1.10.13 had an incomplete fix for CVE-2020-13944, leaving the 'origin' parameter in endpoints like /trigger vulnerable to XSS.
The vulnerability in Apache Airflow stems from an incomplete fix for CVE-2020-13944. The 'origin' parameter, which is passed to endpoints such as '/trigger', was not properly sanitized, leaving it susceptible to Cross-Site Scripting (XSS) attacks [1][3]. This issue affects all Apache Airflow versions prior to 1.10.13 [3]. Despite the initial fix, the implemented sanitization was insufficient and could be bypassed, allowing malicious script injection [1].
An attacker can exploit this vulnerability by crafting a malicious URL containing the 'origin' parameter with embedded JavaScript. When a user clicks on the crafted link or the malicious content is rendered by the Airflow web interface, the injected script executes in the context of the user's browser session [1][3]. No authentication is required beyond the user's existing session; the attacker only needs to trick a user into visiting the crafted link.
Successful exploitation allows an attacker to perform actions on behalf of the victim, such as accessing sensitive data, modifying workflows, or escalating privileges within the Airflow environment [1][3]. Since Airflow is often used to orchestrate data pipelines and manage critical infrastructure, an XSS attack could lead to significant data breaches or operational disruptions.
The issue was addressed in Apache Airflow 1.10.13, but it was later discovered that the fix was incomplete [1][3]. A more robust sanitization was implemented in subsequent releases, including version 2.0.2, which includes the commit "Webserver: Sanitize string passed to origin param" [4]. Users are advised to upgrade to a patched version to mitigate the risk [3].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
apache-airflowPyPI | < 1.10.15rc1 | 1.10.15rc1 |
apache-airflowPyPI | >= 2.0.0b1, < 2.0.2rc1 | 2.0.2rc1 |
Affected products
3- osv-coords2 versions
< 1.10.15+ 1 more
- (no CPE)range: < 1.10.15
- (no CPE)range: < 1.10.15rc1
- Apache Software Foundation/Apache Airflowv5Range: Apache Airflow
Patches
5c6369beed53dWebserver: Sanitize string passed to origin param (#14738)
4 files changed · +53 −13
airflow/www_rbac/views.py+12 −1 modified@@ -100,8 +100,19 @@ def get_safe_url(url): parsed = urlparse(url) + # If the url is relative & it contains semicolon, redirect it to homepage to avoid + # potential XSS. (Similar to https://github.com/python/cpython/pull/24297/files (bpo-42967)) + if parsed.netloc == '' and parsed.scheme == '' and ';' in unquote(url): + return url_for('Airflow.index') + query = parse_qsl(parsed.query, keep_blank_values=True) - url = parsed._replace(query=urlencode(query)).geturl() + + # Remove all the query elements containing semicolon + # As part of https://github.com/python/cpython/pull/24297/files (bpo-42967) + # semicolon was already removed as a separator for query arguments by default + sanitized_query = [query_arg for query_arg in query if ';' not in query_arg[1]] + url = parsed._replace(query=urlencode(sanitized_query)).geturl() + if parsed.scheme in valid_schemes and parsed.netloc in valid_netlocs: return url except Exception as e: # pylint: disable=broad-except
airflow/www/views.py+11 −1 modified@@ -340,8 +340,18 @@ def get_safe_url(url): parsed = urlparse(url) + # If the url is relative & it contains semicolon, redirect it to homepage to avoid + # potential XSS. (Similar to https://github.com/python/cpython/pull/24297/files (bpo-42967)) + if parsed.netloc == '' and parsed.scheme == '' and ';' in unquote(url): + return "/admin/" + query = parse_qsl(parsed.query, keep_blank_values=True) - url = parsed._replace(query=urlencode(query)).geturl() + + # Remove all the query elements containing semicolon + # As part of https://github.com/python/cpython/pull/24297/files (bpo-42967) + # semicolon was already removed as a separator for query arguments by default + sanitized_query = [query_arg for query_arg in query if ';' not in query_arg[1]] + url = parsed._replace(query=urlencode(sanitized_query)).geturl() if parsed.scheme in valid_schemes and parsed.netloc in valid_netlocs: return url except Exception as e: # pylint: disable=broad-except
tests/www_rbac/test_views.py+25 −11 modified@@ -41,7 +41,7 @@ from werkzeug.wrappers import BaseResponse from airflow import models, settings, version -from airflow.configuration import conf +from airflow.configuration import conf, WEBSERVER_CONFIG, _read_default_config_file from airflow.config_templates.airflow_local_settings import DEFAULT_LOGGING_CONFIG from airflow.executors.celery_executor import CeleryExecutor from airflow.jobs import BaseJob @@ -66,15 +66,26 @@ class TestBase(unittest.TestCase): @classmethod def setUpClass(cls): + cls.orig_rbac_conf = conf.get('webserver', 'rbac') + conf.set('webserver', 'rbac', 'True') + cls._create_default_webserver_config() cls.app, cls.appbuilder = application.create_app(session=Session, testing=True) cls.app.config['WTF_CSRF_ENABLED'] = False cls.app.jinja_env.undefined = jinja2.StrictUndefined settings.configure_orm() cls.session = Session + @staticmethod + def _create_default_webserver_config(): + if not os.path.isfile(WEBSERVER_CONFIG): + DEFAULT_WEBSERVER_CONFIG, _ = _read_default_config_file('default_webserver_config.py') + with open(WEBSERVER_CONFIG, 'w') as file: + file.write(DEFAULT_WEBSERVER_CONFIG) + @classmethod def tearDownClass(cls): clear_db_runs() + conf.set('webserver', 'rbac', cls.orig_rbac_conf) def setUp(self): self.client = self.app.test_client() @@ -2244,16 +2255,19 @@ def test_trigger_serialized_dag(self, mock_os_isfile, mock_dagrun): self.check_content_in_response( 'Triggered example_bash_operator, it should start any moment now.', response) - @parameterized.expand([ - ("javascript:alert(1)", "/home"), - ("http://google.com", "/home"), - ( - "%2Ftree%3Fdag_id%3Dexample_bash_operator';alert(33)//", - "/tree?dag_id=example_bash_operator%27&alert%2833%29%2F%2F=", - ), - ("%2Ftree%3Fdag_id%3Dexample_bash_operator", "/tree?dag_id=example_bash_operator"), - ("%2Fgraph%3Fdag_id%3Dexample_bash_operator", "/graph?dag_id=example_bash_operator"), - ]) + @parameterized.expand( + [ + ("javascript:alert(1)", "/home"), + ("http://google.com", "/home"), + ("36539'%3balert(1)%2f%2f166", "/home"), + ( + "%2Ftree%3Fdag_id%3Dexample_bash_operator';alert(33)//", + "/home", + ), + ("%2Ftree%3Fdag_id%3Dexample_bash_operator", "/tree?dag_id=example_bash_operator"), + ("%2Fgraph%3Fdag_id%3Dexample_bash_operator", "/graph?dag_id=example_bash_operator"), + ] + ) def test_trigger_dag_form_origin_url(self, test_origin, expected_origin): test_dag_id = "example_bash_operator"
tests/www/test_views.py+5 −0 modified@@ -1119,6 +1119,11 @@ def test_trigger_serialized_dag(self, mock_os_isfile, mock_dagrun): @parameterized.expand([ ("javascript:alert(1)", "/admin/"), ("http://google.com", "/admin/"), + ("36539'%3balert(1)%2f%2f166", "/admin/"), + ( + "%2Fadmin%2Fairflow%2Ftree%3Fdag_id%3Dexample_bash_operator';alert(33)//", + "/admin/", + ), ( "%2Fadmin%2Fairflow%2Ftree%3Fdag_id%3Dexample_bash_operator" "&dag_id=example_bash_operator';alert(33)//",
ab8c55878e3eWebserver: Sanitize string passed to origin param (#14738)
2 files changed · +20 −19
airflow/www/views.py+11 −1 modified@@ -129,8 +129,18 @@ def get_safe_url(url): parsed = urlparse(url) + # If the url is relative & it contains semicolon, redirect it to homepage to avoid + # potential XSS. (Similar to https://github.com/python/cpython/pull/24297/files (bpo-42967)) + if parsed.netloc == '' and parsed.scheme == '' and ';' in unquote(url): + return url_for('Airflow.index') + query = parse_qsl(parsed.query, keep_blank_values=True) - url = parsed._replace(query=urlencode(query)).geturl() + + # Remove all the query elements containing semicolon + # As part of https://github.com/python/cpython/pull/24297/files (bpo-42967) + # semicolon was already removed as a separator for query arguments by default + sanitized_query = [query_arg for query_arg in query if ';' not in query_arg[1]] + url = parsed._replace(query=urlencode(sanitized_query)).geturl() if parsed.scheme in valid_schemes and parsed.netloc in valid_netlocs: return url
tests/www/test_views.py+9 −18 modified@@ -32,7 +32,7 @@ from typing import Any, Dict, Generator, List, NamedTuple from unittest import mock from unittest.mock import PropertyMock -from urllib.parse import parse_qsl, quote_plus +from urllib.parse import quote_plus import jinja2 import pytest @@ -2755,9 +2755,10 @@ def test_trigger_dag_form(self): [ ("javascript:alert(1)", "/home"), ("http://google.com", "/home"), + ("36539'%3balert(1)%2f%2f166", "/home"), ( "%2Ftree%3Fdag_id%3Dexample_bash_operator';alert(33)//", - "/tree?dag_id=example_bash_operator%27%3Balert%2833%29%2F%2F", + "/home", ), ("%2Ftree%3Fdag_id%3Dexample_bash_operator", "/tree?dag_id=example_bash_operator"), ("%2Fgraph%3Fdag_id%3Dexample_bash_operator", "/graph?dag_id=example_bash_operator"), @@ -2766,13 +2767,6 @@ def test_trigger_dag_form(self): def test_trigger_dag_form_origin_url(self, test_origin, expected_origin): test_dag_id = "example_bash_operator" - # https://github.com/python/cpython/pull/24297/files - # Check if tests are running with a Python version containing the above fix - # where ";" is removed as a separator - if parse_qsl(";a=b") != [(';a', 'b')] and ";" in test_origin: - expected_origin = expected_origin.replace("%3B", "&") - expected_origin += "=" - resp = self.client.get(f'trigger?dag_id={test_dag_id}&origin={test_origin}') self.check_content_in_response( '<button type="button" class="btn" onclick="location.href = \'{}\'; return false">'.format( @@ -3302,10 +3296,14 @@ class TestHelperFunctions(TestBase): [ ("", "/home"), ("http://google.com", "/home"), + ("36539'%3balert(1)%2f%2f166", "/home"), + ( + "http://localhost:8080/trigger?dag_id=test&origin=36539%27%3balert(1)%2f%2f166&abc=2", + "http://localhost:8080/trigger?dag_id=test&abc=2", + ), ( "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag';alert(33)//", - "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3F" - "dag_id%25test_dag%27%3Balert%2833%29%2F%2F", + "http://localhost:8080/trigger?dag_id=test_dag", ), ( "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag", @@ -3315,13 +3313,6 @@ class TestHelperFunctions(TestBase): ) @mock.patch("airflow.www.views.url_for") def test_get_safe_url(self, test_url, expected_url, mock_url_for): - # https://github.com/python/cpython/pull/24297/files - # Check if tests are running with a Python version containing the above fix - # where ";" is removed as a separator - if parse_qsl(";a=b") != [(';a', 'b')] and ";" in test_url: - expected_url = expected_url.replace("%3B", "&") - expected_url += "=" - mock_url_for.return_value = "/home" with self.app.test_request_context(base_url="http://localhost:8080"): assert get_safe_url(test_url) == expected_url
409c249121bdWebserver: Sanitize string passed to origin param (#14738)
2 files changed · +20 −19
airflow/www/views.py+11 −1 modified@@ -129,8 +129,18 @@ def get_safe_url(url): parsed = urlparse(url) + # If the url is relative & it contains semicolon, redirect it to homepage to avoid + # potential XSS. (Similar to https://github.com/python/cpython/pull/24297/files (bpo-42967)) + if parsed.netloc == '' and parsed.scheme == '' and ';' in unquote(url): + return url_for('Airflow.index') + query = parse_qsl(parsed.query, keep_blank_values=True) - url = parsed._replace(query=urlencode(query)).geturl() + + # Remove all the query elements containing semicolon + # As part of https://github.com/python/cpython/pull/24297/files (bpo-42967) + # semicolon was already removed as a separator for query arguments by default + sanitized_query = [query_arg for query_arg in query if ';' not in query_arg[1]] + url = parsed._replace(query=urlencode(sanitized_query)).geturl() if parsed.scheme in valid_schemes and parsed.netloc in valid_netlocs: return url
tests/www/test_views.py+9 −18 modified@@ -32,7 +32,7 @@ from typing import Any, Dict, Generator, List, NamedTuple from unittest import mock from unittest.mock import PropertyMock -from urllib.parse import parse_qsl, quote_plus +from urllib.parse import quote_plus import jinja2 import pytest @@ -2776,9 +2776,10 @@ def test_trigger_dag_form(self): [ ("javascript:alert(1)", "/home"), ("http://google.com", "/home"), + ("36539'%3balert(1)%2f%2f166", "/home"), ( "%2Ftree%3Fdag_id%3Dexample_bash_operator';alert(33)//", - "/tree?dag_id=example_bash_operator%27%3Balert%2833%29%2F%2F", + "/home", ), ("%2Ftree%3Fdag_id%3Dexample_bash_operator", "/tree?dag_id=example_bash_operator"), ("%2Fgraph%3Fdag_id%3Dexample_bash_operator", "/graph?dag_id=example_bash_operator"), @@ -2787,13 +2788,6 @@ def test_trigger_dag_form(self): def test_trigger_dag_form_origin_url(self, test_origin, expected_origin): test_dag_id = "example_bash_operator" - # https://github.com/python/cpython/pull/24297/files - # Check if tests are running with a Python version containing the above fix - # where ";" is removed as a separator - if parse_qsl(";a=b") != [(';a', 'b')] and ";" in test_origin: - expected_origin = expected_origin.replace("%3B", "&") - expected_origin += "=" - resp = self.client.get(f'trigger?dag_id={test_dag_id}&origin={test_origin}') self.check_content_in_response( '<button type="button" class="btn" onclick="location.href = \'{}\'; return false">'.format( @@ -3325,10 +3319,14 @@ class TestHelperFunctions(TestBase): [ ("", "/home"), ("http://google.com", "/home"), + ("36539'%3balert(1)%2f%2f166", "/home"), + ( + "http://localhost:8080/trigger?dag_id=test&origin=36539%27%3balert(1)%2f%2f166&abc=2", + "http://localhost:8080/trigger?dag_id=test&abc=2", + ), ( "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag';alert(33)//", - "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3F" - "dag_id%25test_dag%27%3Balert%2833%29%2F%2F", + "http://localhost:8080/trigger?dag_id=test_dag", ), ( "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag", @@ -3338,13 +3336,6 @@ class TestHelperFunctions(TestBase): ) @mock.patch("airflow.www.views.url_for") def test_get_safe_url(self, test_url, expected_url, mock_url_for): - # https://github.com/python/cpython/pull/24297/files - # Check if tests are running with a Python version containing the above fix - # where ";" is removed as a separator - if parse_qsl(";a=b") != [(';a', 'b')] and ";" in test_url: - expected_url = expected_url.replace("%3B", "&") - expected_url += "=" - mock_url_for.return_value = "/home" with self.app.test_request_context(base_url="http://localhost:8080"): assert get_safe_url(test_url) == expected_url
7486153f451efixup! Webserver: Further Sanitize values passed to origin param
2 files changed · +11 −5
airflow/www/views.py+4 −3 modified@@ -108,11 +108,12 @@ def get_safe_url(url): valid_schemes = ['http', 'https', ''] valid_netlocs = [request.host, ''] - # Remove single quotes - url = url.replace("'", "") + if not url: + return url_for('Airflow.index') + parsed = urlparse(url) - query = parse_qsl(parsed.query) + query = parse_qsl(parsed.query, keep_blank_values=True) url = parsed._replace(query=urlencode(query)).geturl() if parsed.scheme in valid_schemes and parsed.netloc in valid_netlocs:
tests/www/test_views.py+7 −2 modified@@ -2772,7 +2772,10 @@ def test_trigger_dag_form(self): [ ("javascript:alert(1)", "/home"), ("http://google.com", "/home"), - ("%2Ftree%3Fdag_id%3Dexample_bash_operator%27;alert(33)//", "/tree?dag_id=example_bash_operator"), + ( + "%2Ftree%3Fdag_id%3Dexample_bash_operator';alert(33)//", + "/tree?dag_id=example_bash_operator%27&alert%2833%29%2F%2F=", + ), ("%2Ftree%3Fdag_id%3Dexample_bash_operator", "/tree?dag_id=example_bash_operator"), ("%2Fgraph%3Fdag_id%3Dexample_bash_operator", "/graph?dag_id=example_bash_operator"), ] @@ -3299,10 +3302,12 @@ def test_action_logging_post(self): class TestHelperFunctions(unittest.TestCase): @parameterized.expand( [ + ("", "/home"), ("http://google.com", "/home"), ( "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag';alert(33)//", - "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%25test_dag", + "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3F" + "dag_id%25test_dag%27&alert%2833%29%2F%2F=", ), ( "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag",
13336272e328Webserver: Further Sanitize values passed to origin param
2 files changed · +30 −2
airflow/www/views.py+6 −1 modified@@ -28,7 +28,7 @@ from datetime import datetime, timedelta from json import JSONDecodeError from typing import Dict, List, Optional, Tuple -from urllib.parse import unquote, urlparse +from urllib.parse import parse_qsl, unquote, urlencode, urlparse import lazy_object_proxy import nvd3 @@ -108,8 +108,13 @@ def get_safe_url(url): valid_schemes = ['http', 'https', ''] valid_netlocs = [request.host, ''] + # Remove single quotes + url = url.replace("'", "") parsed = urlparse(url) + query = parse_qsl(parsed.query) + url = parsed._replace(query=urlencode(query)).geturl() + if parsed.scheme in valid_schemes and parsed.netloc in valid_netlocs: return url
tests/www/test_views.py+24 −1 modified@@ -62,7 +62,7 @@ from airflow.utils.timezone import datetime from airflow.utils.types import DagRunType from airflow.www import app as application -from airflow.www.views import ConnectionModelView +from airflow.www.views import ConnectionModelView, get_safe_url from tests.test_utils import fab_utils from tests.test_utils.asserts import assert_queries_count from tests.test_utils.config import conf_vars @@ -2772,6 +2772,7 @@ def test_trigger_dag_form(self): [ ("javascript:alert(1)", "/home"), ("http://google.com", "/home"), + ("%2Ftree%3Fdag_id%3Dexample_bash_operator%27;alert(33)//", "/tree?dag_id=example_bash_operator"), ("%2Ftree%3Fdag_id%3Dexample_bash_operator", "/tree?dag_id=example_bash_operator"), ("%2Fgraph%3Fdag_id%3Dexample_bash_operator", "/graph?dag_id=example_bash_operator"), ] @@ -3293,3 +3294,25 @@ def test_action_logging_post(self): self.check_last_log( "example_bash_operator", event="clear", execution_date=self.EXAMPLE_DAG_DEFAULT_DATE ) + + +class TestHelperFunctions(unittest.TestCase): + @parameterized.expand( + [ + ("http://google.com", "/home"), + ( + "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag';alert(33)//", + "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%25test_dag", + ), + ( + "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%test_dag", + "http://localhost:8080/trigger?dag_id=test_dag&origin=%2Ftree%3Fdag_id%25test_dag", + ), + ] + ) + @mock.patch("airflow.www.views.url_for") + @mock.patch("airflow.www.views.request") + def test_get_safe_url(self, test_url, expected_url, mock_req, mock_url_for): + mock_req.host = 'localhost:8080' + mock_url_for.return_value = "/home" + self.assertEqual(get_safe_url(test_url), expected_url)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
26- github.com/advisories/GHSA-86vp-x3pr-79rxghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-17515ghsaADVISORY
- www.openwall.com/lists/oss-security/2020/12/11/2ghsamailing-listx_refsource_MLISTWEB
- www.openwall.com/lists/oss-security/2021/05/01/2ghsamailing-listx_refsource_MLISTWEB
- github.com/apache/airflow/commit/13336272e32872247fa7d17e964ccd88ec8d1376ghsaWEB
- github.com/apache/airflow/commit/409c249121bd9c8902fc2ba551b21873ab41f953ghsaWEB
- github.com/apache/airflow/commit/7486153f451e4d2bb1c6fd9cbb5a63430157c99cghsaWEB
- github.com/apache/airflow/commit/ab8c55878e3e4257d2276226cb17b047ba856686ghsaWEB
- github.com/apache/airflow/commit/c6369beed53d41c0a70415b0d958bf0604124ad7ghsaWEB
- github.com/apache/airflow/pull/14738ghsaWEB
- github.com/apache/airflow/releases/tag/1.10.15ghsaWEB
- github.com/apache/airflow/releases/tag/2.0.2ghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/apache-airflow/PYSEC-2020-21.yamlghsaWEB
- lists.apache.org/thread.html/r2892ef594dbbf54d0939b808626f52f7c2d1584f8aa1d81570847d2a%40%3Cannounce.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/r2892ef594dbbf54d0939b808626f52f7c2d1584f8aa1d81570847d2a%40%3Cdev.airflow.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/r2892ef594dbbf54d0939b808626f52f7c2d1584f8aa1d81570847d2a%40%3Cusers.airflow.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/r2892ef594dbbf54d0939b808626f52f7c2d1584f8aa1d81570847d2a@%3Cannounce.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r2892ef594dbbf54d0939b808626f52f7c2d1584f8aa1d81570847d2a@%3Cdev.airflow.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r2892ef594dbbf54d0939b808626f52f7c2d1584f8aa1d81570847d2a@%3Cusers.airflow.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r4656959c8ed06c1f6202d89aa4e67b35ad7bdba5a666caff3fea888e%40%3Cusers.airflow.apache.org%3Eghsax_refsource_MISCmailing-listx_refsource_MLISTWEB
- lists.apache.org/thread.html/r4656959c8ed06c1f6202d89aa4e67b35ad7bdba5a666caff3fea888e@%3Cusers.airflow.apache.org%3EghsaWEB
- lists.apache.org/thread.html/ra8ce70088ba291f358e077cafdb14d174b7a1ce9a9d86d1b332d6367%40%3Cusers.airflow.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/ra8ce70088ba291f358e077cafdb14d174b7a1ce9a9d86d1b332d6367@%3Cusers.airflow.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rc005f4de9d9b0ba943ceb8ff5a21a5c6ff8a9df52632476698d99432%40%3Cannounce.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/rc005f4de9d9b0ba943ceb8ff5a21a5c6ff8a9df52632476698d99432@%3Cannounce.apache.org%3EghsaWEB
- pypi.org/project/apache-airflowghsaWEB
News mentions
0No linked articles in our index yet.