diff --git a/ee/spec/lib/gitlab/git_access_spec.rb b/ee/spec/lib/gitlab/git_access_spec.rb
index 87041d4d2cf2942adc3d49a36aa8209cba3ef5bc..92d8ff184c190559c8e1bf62a22c5fa12c04e0c1 100644
--- a/ee/spec/lib/gitlab/git_access_spec.rb
+++ b/ee/spec/lib/gitlab/git_access_spec.rb
@@ -1416,7 +1416,7 @@ def sso_session_data
 
       with_them do
         before do
-          stub_session(user_id: user.id, **sso_session_data) if active_session?
+          stub_session(session_data: sso_session_data, user_id: user.id) if active_session?
           user.update!(admin: true) if user_is_admin?
           user.update!(auditor: true) if user_is_auditor?
 
diff --git a/ee/spec/requests/ee/omniauth_callbacks_controller_spec.rb b/ee/spec/requests/ee/omniauth_callbacks_controller_spec.rb
index 7301ef28accfd1a413e391ad7350f563e264bc75..bb639a6d09694df17aa892cd5190778a98702652 100644
--- a/ee/spec/requests/ee/omniauth_callbacks_controller_spec.rb
+++ b/ee/spec/requests/ee/omniauth_callbacks_controller_spec.rb
@@ -24,7 +24,7 @@
       let(:path) { '/user/return/to/path' }
 
       before do
-        stub_session(user_return_to: path)
+        stub_session(session_data: { user_return_to: path })
       end
 
       context 'when onboarding is enabled', :saas do
diff --git a/ee/spec/requests/ee/registrations_controller_spec.rb b/ee/spec/requests/ee/registrations_controller_spec.rb
index d6601ffba3fe789a2635737febcc6eef41fef739..6ca09bdf3a4a55cc84dab79f1d26e0cb275d5dc0 100644
--- a/ee/spec/requests/ee/registrations_controller_spec.rb
+++ b/ee/spec/requests/ee/registrations_controller_spec.rb
@@ -46,7 +46,7 @@
 
       context 'when subscription', :saas, :clean_gitlab_redis_sessions do
         before do
-          stub_session(user_return_to: new_subscriptions_path)
+          stub_session(session_data: { user_return_to: new_subscriptions_path })
         end
 
         it 'tracks successful form submission' do
@@ -311,7 +311,7 @@
 
       context 'when subscription', :saas, :clean_gitlab_redis_sessions do
         before do
-          stub_session(user_return_to: new_subscriptions_path)
+          stub_session(session_data: { user_return_to: new_subscriptions_path })
         end
 
         it 'tracks successful form submission' do
diff --git a/ee/spec/requests/subscriptions_controller_spec.rb b/ee/spec/requests/subscriptions_controller_spec.rb
index 2164bbb3bc391c79daa0126eceed43a01d67edea..6270a8e491c2168cc0ed26b777c485e1a562ca25 100644
--- a/ee/spec/requests/subscriptions_controller_spec.rb
+++ b/ee/spec/requests/subscriptions_controller_spec.rb
@@ -21,7 +21,7 @@
       let_it_be(:unverified_user) { create(:user) }
 
       before do
-        stub_session(verification_user_id: unverified_user.id)
+        stub_session(session_data: { verification_user_id: unverified_user.id })
       end
 
       it 'skips authentication' do
@@ -51,7 +51,7 @@
       let_it_be(:unverified_user) { create(:user) }
 
       before do
-        stub_session(verification_user_id: unverified_user.id)
+        stub_session(session_data: { verification_user_id: unverified_user.id })
       end
 
       it 'validates the payment method with the unverified user ID' do
diff --git a/ee/spec/requests/users/registrations_identity_verification_controller_spec.rb b/ee/spec/requests/users/registrations_identity_verification_controller_spec.rb
index 4923af47349c5a5570d80255e2bf891e1cc5f6a5..0058614e21d2fdf900ae8147d31424e7e1b78f12 100644
--- a/ee/spec/requests/users/registrations_identity_verification_controller_spec.rb
+++ b/ee/spec/requests/users/registrations_identity_verification_controller_spec.rb
@@ -53,7 +53,7 @@
 
     context 'when session contains an invalid `verification_user_id`' do
       before do
-        stub_session(verification_user_id: invalid_verification_user_id)
+        stub_session(session_data: { verification_user_id: invalid_verification_user_id })
       end
 
       it 'handles sticking' do
@@ -81,7 +81,7 @@
 
     context 'when session contains a valid `verification_user_id`' do
       before do
-        stub_session(verification_user_id: unconfirmed_user.id)
+        stub_session(session_data: { verification_user_id: unconfirmed_user.id })
 
         do_request
       end
@@ -97,7 +97,7 @@
 
     context 'when session is empty but a confirmed user is logged in' do
       before do
-        stub_session(verification_user_id: nil)
+        stub_session(session_data: { verification_user_id: nil })
         sign_in confirmed_user
 
         do_request
@@ -119,7 +119,7 @@
     let(:response_code) { expected_response_code || :ok }
 
     before do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
 
       do_request
     end
@@ -166,7 +166,7 @@
     let(:user) { create(:omniauth_user, :unconfirmed) }
 
     before do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
 
       do_request
     end
@@ -301,7 +301,7 @@
   shared_examples 'it loads reCAPTCHA' do
     before do
       stub_feature_flags(arkose_labs_phone_verification_challenge: false)
-      stub_session(verification_user_id: unconfirmed_user.id)
+      stub_session(session_data: { verification_user_id: unconfirmed_user.id })
     end
 
     context 'when reCAPTCHA is disabled' do
@@ -451,7 +451,7 @@
     it_behaves_like 'it loads reCAPTCHA'
 
     it 'renders template show with layout minimal' do
-      stub_session(verification_user_id: unconfirmed_user.id)
+      stub_session(session_data: { verification_user_id: unconfirmed_user.id })
 
       do_request
 
@@ -462,7 +462,7 @@
       let(:experiment) { instance_double(ApplicationExperiment) }
 
       it 'tracks signup_intent_step_one experiment events' do
-        stub_session(verification_user_id: unconfirmed_user.id)
+        stub_session(session_data: { verification_user_id: unconfirmed_user.id })
 
         allow_next_instance_of(described_class) do |controller|
           allow(controller)
@@ -489,7 +489,7 @@
       with_them do
         before do
           allow(Gitlab).to receive(:com?).and_return(dot_com)
-          stub_session(verification_user_id: user.id)
+          stub_session(session_data: { verification_user_id: user.id })
           user.ban
 
           do_request
@@ -527,7 +527,7 @@
       let_it_be(:user) { unconfirmed_user }
 
       before do
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
       end
 
       it 'returns verification methods and state' do
@@ -578,7 +578,7 @@
         allow(service).to receive(:execute).and_return(service_response)
       end
 
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
     end
 
     it_behaves_like 'it requires a valid verification_user_id'
@@ -629,7 +629,7 @@
         allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?)
           .with(:email_verification_code_send, scope: user).and_return(true)
 
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
 
         do_request
       end
@@ -651,7 +651,7 @@
         allow_next_instance_of(::Users::EmailVerification::GenerateTokenService) do |service|
           allow(service).to receive(:generate_token).and_return(new_token)
         end
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
       end
 
       it 'sets the confirmation_sent_at time', :freeze_time do
@@ -693,7 +693,7 @@
       allow_next_instance_of(::PhoneVerification::Users::SendVerificationCodeService) do |service|
         allow(service).to receive(:execute).and_return(service_response)
       end
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
     end
 
     it_behaves_like 'it requires a valid verification_user_id'
@@ -752,7 +752,7 @@
       allow_next_instance_of(::PhoneVerification::Users::VerifyCodeService) do |service|
         allow(service).to receive(:execute).and_return(service_response)
       end
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
     end
 
     it_behaves_like 'it requires a valid verification_user_id'
@@ -791,7 +791,7 @@
     let_it_be(:user_with_risk_band) { create(:user) }
 
     before do
-      stub_session(verification_user_id: user&.id)
+      stub_session(session_data: { verification_user_id: user&.id })
       request
     end
 
@@ -824,7 +824,7 @@
     let(:service_response) { successful_verification_response }
 
     before do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
 
       allow_next_instance_of(Arkose::TokenVerificationService) do |instance|
         allow(instance).to receive(:execute).and_return(service_response)
@@ -891,7 +891,7 @@
     it_behaves_like 'it requires an unconfirmed user'
 
     it 'renders arkose_labs_challenge template' do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
       do_request
 
       expect(response).to render_template('arkose_labs_challenge', layout: 'minimal')
@@ -904,7 +904,7 @@
     let(:user) { confirmed_user }
 
     before do
-      stub_session(**{ verification_user_id: user.id }.merge(return_to_entries))
+      stub_session(session_data: { verification_user_id: user.id }.merge(return_to_entries))
     end
 
     context 'for an invite' do
@@ -980,7 +980,7 @@
     let_it_be(:user) { unconfirmed_user }
 
     before do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
     end
 
     subject(:do_request) { get verify_credit_card_signup_identity_verification_path(params) }
@@ -1107,7 +1107,7 @@
     let_it_be(:user) { unconfirmed_user }
 
     before do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
     end
 
     subject(:do_request) { post verify_credit_card_captcha_signup_identity_verification_path }
@@ -1122,7 +1122,7 @@
     subject(:do_request) { patch toggle_phone_exemption_signup_identity_verification_path(format: :json) }
 
     before do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
     end
 
     it_behaves_like 'it requires an unconfirmed user'
diff --git a/spec/channels/application_cable/connection_spec.rb b/spec/channels/application_cable/connection_spec.rb
index 28a852c46fa08802d3e80fd988b137aea3642b97..d4e5fd3ab3a941a5c0675593614d2924e476e596 100644
--- a/spec/channels/application_cable/connection_spec.rb
+++ b/spec/channels/application_cable/connection_spec.rb
@@ -7,7 +7,7 @@
 
   context 'when session cookie is set' do
     before do
-      stub_session(**session_hash)
+      stub_session(session_data: session_hash)
     end
 
     context 'when user is logged in' do
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 9d1e28af13080747b1ce1d4684f59a88766aaf4c..8a0ed027aae5bdb1672af39c5cb4563e97b9a47a 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -599,7 +599,7 @@
 
       context 'when using warden', :snowplow, :clean_gitlab_redis_sessions do
         before do
-          stub_session('warden.user.user.key' => [[user.id], user.authenticatable_salt])
+          stub_session(session_data: { 'warden.user.user.key' => [[user.id], user.authenticatable_salt] })
         end
 
         subject { post api(url), params: valid_c_params }
diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
index b9dd7c562ab8205c082144db757011059103d92a..0e60b047db465478a5c8e4bf094e1710bbb1cb10 100644
--- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
@@ -197,7 +197,11 @@ def blob_at(filename)
 
       context 'when not sessionless', :clean_gitlab_redis_sessions do
         before do
-          stub_session('warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt])
+          stub_session(
+            session_data: {
+              'warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt]
+            }
+          )
         end
 
         it_behaves_like 'internal event tracking' do
diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb
index a433686d5d949b6f066b7d6be9ba8505fabe1b1a..f5894341e51c450a4d50b761963934e3b78d1459 100644
--- a/spec/requests/api/internal/kubernetes_spec.rb
+++ b/spec/requests/api/internal/kubernetes_spec.rb
@@ -533,15 +533,19 @@ def send_request(headers: {}, params: {})
 
     def stub_user_session(user, csrf_token)
       stub_session(
-        'warden.user.user.key' => [[user.id], user.authenticatable_salt],
-        '_csrf_token' => csrf_token
+        session_data: {
+          'warden.user.user.key' => [[user.id], user.authenticatable_salt],
+          '_csrf_token' => csrf_token
+        }
       )
     end
 
     def stub_user_session_with_no_user_id(user, csrf_token)
       stub_session(
-        'warden.user.user.key' => [[nil], user.authenticatable_salt],
-        '_csrf_token' => csrf_token
+        session_data: {
+          'warden.user.user.key' => [[nil], user.authenticatable_salt],
+          '_csrf_token' => csrf_token
+        }
       )
     end
 
diff --git a/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb
index 427eff8cd76b32567b5b9b8b5fee28b1e34c63f3..936774b866fdbd208dc872d2276ad2cf0f55b3ab 100644
--- a/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb
+++ b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb
@@ -14,7 +14,7 @@
     before do
       sign_in(user)
 
-      stub_session(GoogleApi::CloudPlatform::Client.session_key_for_token => 'token')
+      stub_session(session_data: { GoogleApi::CloudPlatform::Client.session_key_for_token => 'token' })
 
       allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
         allow(client).to receive(:validate_token).and_return(true)
diff --git a/spec/requests/verifies_with_email_spec.rb b/spec/requests/verifies_with_email_spec.rb
index c8a0c0975a3baa517f4a9dc1f37922d535d64112..15d85ae82eb350195f26b65b55a6c2624bd45fbc 100644
--- a/spec/requests/verifies_with_email_spec.rb
+++ b/spec/requests/verifies_with_email_spec.rb
@@ -147,7 +147,7 @@
       before do
         encrypted_token = Devise.token_generator.digest(User, user.email, 'token')
         user.update!(locked_at: Time.current, unlock_token: encrypted_token)
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
       end
 
       context 'when rate limited and a verification_token param exists' do
@@ -305,7 +305,7 @@
 
     context 'when a verification_user_id session variable exists' do
       before do
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
 
         perform_enqueued_jobs do
           post(users_resend_verification_code_path)
@@ -319,7 +319,7 @@
       before do
         allow(Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true)
 
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
 
         perform_enqueued_jobs do
           post(users_resend_verification_code_path)
@@ -355,7 +355,7 @@
 
     context 'when a verification_user_id session variable exists' do
       before do
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
       end
 
       it 'locks the user' do
@@ -397,7 +397,7 @@
       end
 
       before do
-        stub_session(verification_user_id: user.id)
+        stub_session(session_data: { verification_user_id: user.id })
       end
 
       it 'calls the UpdateEmailService and returns an error response' do
@@ -419,7 +419,7 @@
     end
 
     it 'renders the template and removes the verification_user_id session variable' do
-      stub_session(verification_user_id: user.id)
+      stub_session(session_data: { verification_user_id: user.id })
 
       get(users_successful_verification_path)
 
diff --git a/spec/routing/user_routing_spec.rb b/spec/routing/user_routing_spec.rb
index b155560c9f07bbac0e21b4592c279901d3ae4672..7aa6a8c731c92e46ccb5941558d29c50aaba2d3c 100644
--- a/spec/routing/user_routing_spec.rb
+++ b/spec/routing/user_routing_spec.rb
@@ -11,7 +11,7 @@
 
   context 'when GitHub OAuth on sign in is cancelled' do
     before do
-      stub_session(auth_on_failure_path: '/projects/new#import_project')
+      stub_session(session_data: { auth_on_failure_path: '/projects/new#import_project' })
     end
 
     context 'when all required parameters are present' do
diff --git a/spec/support/helpers/session_helpers.rb b/spec/support/helpers/session_helpers.rb
index ead9087d7a8e94ac326a3d28f29dd39c123ad322..359bc5039dce649406f17c625c564e23dcdeab6c 100644
--- a/spec/support/helpers/session_helpers.rb
+++ b/spec/support/helpers/session_helpers.rb
@@ -3,7 +3,7 @@
 module SessionHelpers
   # Stub a session in Redis, for use in request specs where we can't mock the session directly.
   # This also needs the :clean_gitlab_redis_sessions tag on the spec.
-  def stub_session(user_id: nil, **session_hash)
+  def stub_session(session_data:, user_id: nil)
     unless RSpec.current_example.metadata[:clean_gitlab_redis_sessions]
       raise 'Add :clean_gitlab_redis_sessions to your spec!'
     end
@@ -11,7 +11,7 @@ def stub_session(user_id: nil, **session_hash)
     session_id = Rack::Session::SessionId.new(SecureRandom.hex)
 
     Gitlab::Redis::Sessions.with do |redis|
-      redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
+      redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_data))
       redis.sadd("session:lookup:user:gitlab:#{user_id}", [session_id.private_id]) if user_id
     end
 
diff --git a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
index 8ed3464b009034408e3e9067425a64a2e8cffdf3..82a2c0dd7cbfe9441c7bd61d208bbaa48263b812 100644
--- a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
@@ -22,7 +22,11 @@
 
   context 'when user is not sessionless', :clean_gitlab_redis_sessions do
     before do
-      stub_session('warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt])
+      stub_session(
+        session_data: {
+          'warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt]
+        }
+      )
     end
 
     subject do
diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
index ca6c2ec4f2944930dd58801c2307b826df8ac8ec..89ae165f3fab6bf709fa9750f5a063df9ad5264e 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -683,7 +683,7 @@ def expect_not_found(&block)
       "#{throttle_setting_prefix}_deprecated_api_enabled" => true
     )
 
-    stub_session(**csrf_session)
+    stub_session(session_data: csrf_session)
   end
 
   context 'with a CSRF token' do
@@ -703,7 +703,7 @@ def expect_not_found(&block)
     end
 
     context 'without a CSRF session' do
-      let(:csrf_session) { {} }
+      let(:csrf_session) { nil }
 
       it 'always uses the rate limit for API requests' do
         requests_per_period.times { get_api csrf: true }