From 91aa3dc70dc6732fa98d61bef4ab056633b50aef Mon Sep 17 00:00:00 2001 From: ds-mariole Date: Fri, 29 May 2026 15:41:23 +0200 Subject: [PATCH 1/2] SSASSF-2982: Fix token expiration rule --- lib/secure_api/api_token/validation.rb | 2 +- test/api_token_test.rb | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/secure_api/api_token/validation.rb b/lib/secure_api/api_token/validation.rb index 7b1a731..340ebb9 100644 --- a/lib/secure_api/api_token/validation.rb +++ b/lib/secure_api/api_token/validation.rb @@ -85,7 +85,7 @@ def within_time_tolerance(clear_token) clear_token[/#{prefix}([0-9]+)#{suffix}/] token_time = $1 || 0 elapsed_time = timestamp.to_i - token_time.to_i - elapsed_time < time_tolerance_seconds + elapsed_time >= 0 && elapsed_time < time_tolerance_seconds end end end diff --git a/test/api_token_test.rb b/test/api_token_test.rb index 9d7f70f..bad31a9 100644 --- a/test/api_token_test.rb +++ b/test/api_token_test.rb @@ -52,6 +52,13 @@ def test_a_token_with_the_correct_info_and_time_stamp_gt_10_mins_old_is_invalid end end + def test_a_token_with_a_future_timestamp_is_invalid + twenty_minutes_ago = Time.now.utc.to_i - (60 * 20) + ApiToken.stub(:timestamp, twenty_minutes_ago) do + refute ApiToken.valid?(@token) + end + end + def test_legacy_encryption_and_decryption_when_enabled SecureApi.configure do |config| config.secure_api_pass_phrase = 'test pass phrase' From e3892380fb05417a3e3f4213491e2de6e1068cab Mon Sep 17 00:00:00 2001 From: ds-mariole Date: Fri, 29 May 2026 15:57:59 +0200 Subject: [PATCH 2/2] Fix within_time_tolerance to reject unbounded future timestamps using symmetric tolerance Use elapsed_time.abs so tokens from slightly-ahead servers (within the 10-minute clock-skew window) remain valid, while timestamps beyond the tolerance in either direction are rejected. Co-Authored-By: Claude Sonnet 4.6 --- lib/secure_api/api_token/validation.rb | 2 +- test/api_token_test.rb | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/secure_api/api_token/validation.rb b/lib/secure_api/api_token/validation.rb index 340ebb9..3e7e9a3 100644 --- a/lib/secure_api/api_token/validation.rb +++ b/lib/secure_api/api_token/validation.rb @@ -85,7 +85,7 @@ def within_time_tolerance(clear_token) clear_token[/#{prefix}([0-9]+)#{suffix}/] token_time = $1 || 0 elapsed_time = timestamp.to_i - token_time.to_i - elapsed_time >= 0 && elapsed_time < time_tolerance_seconds + elapsed_time.abs < time_tolerance_seconds end end end diff --git a/test/api_token_test.rb b/test/api_token_test.rb index bad31a9..1525ec5 100644 --- a/test/api_token_test.rb +++ b/test/api_token_test.rb @@ -52,13 +52,20 @@ def test_a_token_with_the_correct_info_and_time_stamp_gt_10_mins_old_is_invalid end end - def test_a_token_with_a_future_timestamp_is_invalid + def test_a_token_with_a_future_timestamp_beyond_tolerance_is_invalid twenty_minutes_ago = Time.now.utc.to_i - (60 * 20) ApiToken.stub(:timestamp, twenty_minutes_ago) do refute ApiToken.valid?(@token) end end + def test_a_token_with_a_future_timestamp_within_tolerance_is_valid + nine_minutes_ago = Time.now.utc.to_i - (60 * 9) + ApiToken.stub(:timestamp, nine_minutes_ago) do + assert ApiToken.valid?(@token) + end + end + def test_legacy_encryption_and_decryption_when_enabled SecureApi.configure do |config| config.secure_api_pass_phrase = 'test pass phrase'