This is an automated email from the ASF dual-hosted git repository.
vincbeck pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-1-test by this push:
new f6e93b3cdaa Add regression tests for _cli_safe_flash escaping in FAB
auth manager (#69540)
f6e93b3cdaa is described below
commit f6e93b3cdaa3e58492765df33aebe806d0a63b67
Author: Sanskar121543 <[email protected]>
AuthorDate: Tue Jul 7 18:32:19 2026 +0400
Add regression tests for _cli_safe_flash escaping in FAB auth manager
(#69540)
* Add regression tests for cli safe flash escaping
* Remove invalid azure role-keys test, keep _cli_safe_flash regression tests
The removed test asserted role_keys populated from a 'groups' claim via
an AUTH_OAUTH_ROLE_KEYS config key that does not exist in the codebase;
get_oauth_user_info() reads the 'roles' claim only, so the assertion
can never pass (verified failing locally). The remaining _cli_safe_flash
tests pass against the branch source.
---------
Co-authored-by: Sanskar121543
<[email protected]>
---
.../auth_manager/security_manager/test_override.py | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git
a/providers/fab/tests/unit/fab/auth_manager/security_manager/test_override.py
b/providers/fab/tests/unit/fab/auth_manager/security_manager/test_override.py
index 7b9e9696e57..1d72ce82109 100644
---
a/providers/fab/tests/unit/fab/auth_manager/security_manager/test_override.py
+++
b/providers/fab/tests/unit/fab/auth_manager/security_manager/test_override.py
@@ -247,3 +247,50 @@ class TestFabAirflowSecurityManagerOverride:
sm._decode_and_validate_azure_jwt = Mock(return_value=resp)
sm._get_authentik_token_info = Mock(return_value=resp)
assert sm.get_oauth_user_info(provider, {"id_token": None}) ==
user_info
+
+
@mock.patch("airflow.providers.fab.auth_manager.security_manager.override.flash")
+
@mock.patch("airflow.providers.fab.auth_manager.security_manager.override.has_request_context")
+ def test_cli_safe_flash_passes_preescaped_html_to_flash(
+ self,
+ mock_has_request_context,
+ mock_flash,
+ ):
+ """_cli_safe_flash does not escape; callers must escape user input
before calling it.
+
+ Callers use escape(user.username) before embedding in the message
string.
+ This test verifies that pre-escaped content reaches flash() intact as
Markup.
+ """
+ mock_has_request_context.return_value = True
+
+ raw_username = "<script>alert('xss')</script>"
+ # Simulate what call sites do: escape(user.username) before calling
_cli_safe_flash
+ safe_username = "<script>alert('xss')</script>"
+
+ EmptySecurityManager._cli_safe_flash(
+ f"User {safe_username} already exists",
+ "warning",
+ )
+
+ flash_arg = mock_flash.call_args[0][0]
+
+ # The raw, unescaped tag must not appear - escaping at call site
prevents XSS
+ assert raw_username not in str(flash_arg)
+ # The pre-escaped content is preserved intact by the Markup wrapping
+ assert safe_username in str(flash_arg)
+
+
@mock.patch("airflow.providers.fab.auth_manager.security_manager.override.log")
+
@mock.patch("airflow.providers.fab.auth_manager.security_manager.override.has_request_context")
+ def test_cli_safe_flash_formats_cli_output(
+ self,
+ mock_has_request_context,
+ mock_log,
+ ):
+ """Outside a web context, _cli_safe_flash converts HTML tags to
terminal-safe text."""
+ mock_has_request_context.return_value = False
+
+ EmptySecurityManager._cli_safe_flash(
+ "Hello<br><b>World</b>",
+ "warning",
+ )
+
+ mock_log.warning.assert_called_once_with("Hello\n*World*")