-
Notifications
You must be signed in to change notification settings - Fork 325
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix XSS on error messages in flash messages from external providers.
- Loading branch information
Showing
3 changed files
with
139 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
require_relative "../test_helper" | ||
|
||
class Test::AdminUi::TestFlashMessagesHtmlSafety < Minitest::Capybara::Test | ||
include Capybara::Screenshot::MiniTestPlugin | ||
include ApiUmbrellaTestHelpers::Setup | ||
include ApiUmbrellaTestHelpers::AdminAuth | ||
include ApiUmbrellaTestHelpers::AdminUiLogin | ||
include Minitest::Hooks | ||
|
||
def setup | ||
super | ||
setup_server | ||
once_per_class_setup do | ||
override_config_set({ | ||
# While the contact URL should be trusted, since it's configured by an | ||
# admin, still test with special character to ensure it's escaped | ||
# properly. | ||
"contact_url" => "https://example.com/contact/?q='\"><script>alert('hello')</script>", | ||
"web" => { | ||
"admin" => { | ||
"auth_strategies" => { | ||
"enabled" => [ | ||
"google", | ||
"max.gov", | ||
], | ||
"max.gov" => { | ||
"require_mfa" => true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, ["--router", "--web"]) | ||
end | ||
end | ||
|
||
def after_all | ||
super | ||
override_config_reset(["--router", "--web"]) | ||
end | ||
|
||
def test_unverified_html_message | ||
omniauth_data = { | ||
"provider" => "google_oauth2", | ||
"info" => { | ||
"email" => "[email protected]", | ||
}, | ||
"extra" => { | ||
"raw_info" => { | ||
"email_verified" => false, | ||
}, | ||
}, | ||
} | ||
|
||
mock_omniauth(omniauth_data) do | ||
assert_login_forbidden("Sign in with Google", "not verified") | ||
assert_match("The email address '[email protected]' is not verified. Please <a href=\"https://example.com/contact/?q='"><script>alert('hello')</script>\">contact us</a> for further assistance.", page.body) | ||
end | ||
end | ||
|
||
def test_unverified_html_message_with_xss_email | ||
omniauth_data = { | ||
"provider" => "google_oauth2", | ||
"info" => { | ||
"email" => "'\"><script>alert('hello')</script>", | ||
}, | ||
"extra" => { | ||
"raw_info" => { | ||
"email_verified" => false, | ||
}, | ||
}, | ||
} | ||
|
||
mock_omniauth(omniauth_data) do | ||
assert_login_forbidden("Sign in with Google", "not verified") | ||
assert_match("The email address ''\"><script>alert('hello')</script>' is not verified. Please <a href=\"https://example.com/contact/?q='"><script>alert('hello')</script>\">contact us</a> for further assistance.", page.body) | ||
end | ||
end | ||
|
||
def test_nonexistent_html_message | ||
omniauth_data = { | ||
"provider" => "google_oauth2", | ||
"info" => { | ||
"email" => "[email protected]", | ||
}, | ||
"extra" => { | ||
"raw_info" => { | ||
"email_verified" => true, | ||
}, | ||
}, | ||
} | ||
|
||
mock_omniauth(omniauth_data) do | ||
assert_login_forbidden("Sign in with Google", "not authorized") | ||
assert_match("The account for '[email protected]' is not authorized to access the admin. Please <a href=\"https://example.com/contact/?q='"><script>alert('hello')</script>\">contact us</a> for further assistance.", page.body) | ||
end | ||
end | ||
|
||
def test_nonexistent_html_message_with_xss_email | ||
omniauth_data = { | ||
"provider" => "google_oauth2", | ||
"info" => { | ||
"email" => "'\"><script>alert('hello')</script>", | ||
}, | ||
"extra" => { | ||
"raw_info" => { | ||
"email_verified" => true, | ||
}, | ||
}, | ||
} | ||
|
||
mock_omniauth(omniauth_data) do | ||
assert_login_forbidden("Sign in with Google", "not authorized") | ||
assert_match("The account for ''\"><script>alert('hello')</script>' is not authorized to access the admin. Please <a href=\"https://example.com/contact/?q='"><script>alert('hello')</script>\">contact us</a> for further assistance.", page.body) | ||
end | ||
end | ||
|
||
def test_mfa_required_html_message | ||
omniauth_data = { | ||
"provider" => "cas", | ||
"info" => { | ||
"email" => "[email protected]", | ||
}, | ||
} | ||
|
||
mock_omniauth(omniauth_data) do | ||
assert_login_forbidden("Sign in with MAX.gov", "must use multi-factor") | ||
assert_match("You must use multi-factor authentication to sign in. Please try again, or <a href=\"https://example.com/contact/?q='"><script>alert('hello')</script>\">contact us</a> for further assistance.", page.body) | ||
end | ||
end | ||
|
||
def test_error_message_from_external_provider | ||
visit "/admins/auth/google_oauth2/callback?error='\"><script>confirm(document.domain)</script>" | ||
assert_match("Could not authenticate you from GoogleOauth2 because \"'\"><script>confirm(document.domain)</script>\".", page.body) | ||
end | ||
end |