test(security): regression test for session cookie after logout (#24713) (#40201)

Co-authored-by: Claude Code <noreply@anthropic.com>
This commit is contained in:
Evan Rusackas
2026-05-18 07:20:51 -07:00
committed by GitHub
parent 453f49ce33
commit 53d5c41a72

View File

@@ -30,6 +30,7 @@ from superset.utils import json
from tests.conftest import with_config
from tests.integration_tests.base_tests import SupersetTestCase
from tests.integration_tests.constants import ADMIN_USERNAME, GAMMA_USERNAME
from tests.integration_tests.test_app import app
from tests.integration_tests.fixtures.birth_names_dashboard import (
load_birth_names_dashboard_with_slices, # noqa: F401
load_birth_names_data, # noqa: F401
@@ -402,3 +403,42 @@ class TestSecurityRolesApi(SupersetTestCase):
assert sorted(role2_api["user_ids"]) == role2_expected["user_ids"]
assert sorted(role2_api["permission_ids"]) == role2_expected["permission_ids"]
assert role2_api["group_ids"] == role2_expected["group_ids"]
class TestLogoutSessionInvalidation(SupersetTestCase):
"""Regression for #24713: a session cookie captured pre-logout must not grant
access after the user logs out. The original report describes copying the
session cookie out, calling /logout/, and successfully reusing the cookie in
a second browser to bypass authentication."""
def test_session_cookie_invalidated_after_logout(self):
self.login(ADMIN_USERNAME)
resp_authed = self.client.get("api/v1/dashboard/", follow_redirects=False)
assert resp_authed.status_code == 200, (
f"Login did not yield an authenticated session "
f"(got {resp_authed.status_code})"
)
# Werkzeug 2.3+ exposes the test client's cookies on `_cookies` as a
# mapping keyed by (domain, path, key). Snapshot the session cookie
# value — this is what a malicious actor would copy out of a browser.
captured = None
for cookie in self.client._cookies.values():
if cookie.key == "session":
captured = cookie.value
break
assert captured, "expected a session cookie after login"
self.client.get("/logout/", follow_redirects=True)
# Replay the captured cookie in a fresh client (simulates importing
# the cookie into a second browser).
replay_client = app.test_client()
replay_client.set_cookie("session", captured, domain="localhost")
resp_replay = replay_client.get("api/v1/dashboard/", follow_redirects=False)
assert resp_replay.status_code != 200, (
f"Captured session cookie was still accepted after logout "
f"(status={resp_replay.status_code}); see issue #24713"
)