Skip to content

ARSN-560: return AccessDenied error if x-amz-timestamp values before epoch#2599

Merged
bert-e merged 2 commits intodevelopment/8.2from
bugfix/ARSN-560-error-with-date-before-epoch
Mar 25, 2026
Merged

ARSN-560: return AccessDenied error if x-amz-timestamp values before epoch#2599
bert-e merged 2 commits intodevelopment/8.2from
bugfix/ARSN-560-error-with-date-before-epoch

Conversation

@leif-scality
Copy link
Contributor

@leif-scality leif-scality commented Mar 23, 2026

Issue

The ceph s3-tests test_object_create_bad_amz_date_before_epoch_aws4 and test_bucket_create_bad_amz_date_before_epoch_aws4 are failing in CI. These tests send an AWS4-signed request with X-Amz-Date: 19500707T215304Z (pre-Unix epoch, 1950) and expect a 403 with error code AccessDenied or SignatureDoesNotMatch.

Cloudserver returns RequestTimeTooSkewed instead, causing an AssertionError.

Root cause

The regression was introduced in arsenal commit e3223a7 (ARSN-552, 2026-02-11). The old headerAuthCheck.ts had an inline check that explicitly rejected pre-1970 dates: Number.parseInt(xAmzDateArr[0], 10) > 19700101

ARSN-552 replaced this with a call to the new isValidISO8601Compact function, which no longer rejects pre-1970 dates — JavaScript's Date handles them fine as negative Unix timestamps, so the round-trip validation passes for 1950-07-07.

With a valid timestamp, execution reaches validateCredentials, which compares the credential scope date (20260323) against the x-amz-date timestamp date (19500707), finds a mismatch, and returns RequestTimeTooSkewed — the wrong error.

Fix

Add a pre-1970 guard in isValidISO8601Compact in arsenal/lib/auth/v4/timeUtils.ts, restoring the original behavior:

  const [, year, month, day, hour, minute, second] = match;
  if (parseInt(year, 10) < 1970) {
      return false;
  }

With this fix, isValidISO8601Compact('19500707T215304Z') returns false, timestamp stays undefined, and headerAuthCheck returns AccessDenied — matching the test expectation and the pre-ARSN-552 behavior.

@bert-e
Copy link
Contributor

bert-e commented Mar 23, 2026

Hello leif-scality,

My role is to assist you with the merge of this
pull request. Please type @bert-e help to get information
on this process, or consult the user documentation.

Available options
name description privileged authored
/after_pull_request Wait for the given pull request id to be merged before continuing with the current one.
/bypass_author_approval Bypass the pull request author's approval
/bypass_build_status Bypass the build and test status
/bypass_commit_size Bypass the check on the size of the changeset TBA
/bypass_incompatible_branch Bypass the check on the source branch prefix
/bypass_jira_check Bypass the Jira issue check
/bypass_peer_approval Bypass the pull request peers' approval
/bypass_leader_approval Bypass the pull request leaders' approval
/approve Instruct Bert-E that the author has approved the pull request. ✍️
/create_pull_requests Allow the creation of integration pull requests.
/create_integration_branches Allow the creation of integration branches.
/no_octopus Prevent Wall-E from doing any octopus merge and use multiple consecutive merge instead
/unanimity Change review acceptance criteria from one reviewer at least to all reviewers
/wait Instruct Bert-E not to run until further notice.
Available commands
name description privileged
/help Print Bert-E's manual in the pull request.
/status Print Bert-E's current status in the pull request TBA
/clear Remove all comments from Bert-E from the history TBA
/retry Re-start a fresh build TBA
/build Re-start a fresh build TBA
/force_reset Delete integration branches & pull requests, and restart merge process from the beginning.
/reset Try to remove integration branches unless there are commits on them which do not appear on the source branch.

Status report is not available.

@bert-e
Copy link
Contributor

bert-e commented Mar 23, 2026

Incorrect fix version

The Fix Version/s in issue ARSN-560 contains:

  • None

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 8.3.8

Please check the Fix Version/s of ARSN-560, or the target
branch of this pull request.

@codecov
Copy link

codecov bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 90.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.98%. Comparing base (4be7ad2) to head (362f790).
⚠️ Report is 2 commits behind head on development/8.2.

Files with missing lines Patch % Lines
lib/auth/v4/headerAuthCheck.ts 90.47% 2 Missing ⚠️
lib/auth/v4/timeUtils.ts 88.88% 1 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                 @@
##           development/8.2    #2599      +/-   ##
===================================================
+ Coverage            71.96%   71.98%   +0.01%     
===================================================
  Files                  222      222              
  Lines                17940    17954      +14     
  Branches              3734     3738       +4     
===================================================
+ Hits                 12911    12924      +13     
- Misses                5025     5026       +1     
  Partials                 4        4              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@fredmnl fredmnl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two comments come to mind but I'm not coming with a solution, so apologies for that. Other than that, I'm all good with the analysis and the intent of the fix.

* isValidISO8601Compact('20160208T251405Z'); // false (25 hours invalid)
* isValidISO8601Compact('2016-02-08T20:14:05Z'); // false (wrong format)
* isValidISO8601Compact('abcd0208T201405Z'); // false (contains letters)
* isValidISO8601Compact('19500707T215304Z'); // false (pre-Unix epoch)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major. Semantically checking for < 1970 in isValidISO8601Compact isn't great because we are now denying valid ISO8601 inputs. 19500707T215304Z is actually a valid ISO8601 compact time

Copy link
Contributor Author

@leif-scality leif-scality Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced isValidISO8601Compact with ParseISO8601Compact that returns a Date object if it managed to parse the string, the epoch check is done outside the function using date.getTime() < 0


const [, year, month, day, hour, minute, second] = match;

if (parseInt(year, 10) < 1970) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. If it's easy to do, I would prefer unix < 0 rather than year < 1970 which would be a bit more meaningful. If it's adding more than a single line of code, I'm fine with keeping it written that way.

Copy link
Contributor Author

@leif-scality leif-scality Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced isValidISO8601Compact with ParseISO8601Compact that returns a Date object if it managed to parse the string, the epoch check is done outside the function using date.getTime() < 0

@leif-scality leif-scality force-pushed the bugfix/ARSN-560-error-with-date-before-epoch branch from 0724e6e to 13381ac Compare March 24, 2026 11:52
@bert-e
Copy link
Contributor

bert-e commented Mar 24, 2026

Branches have diverged

This pull request's source branch bugfix/ARSN-560-error-with-date-before-epoch has diverged from
development/8.3 by more than 50 commits.

To avoid any integration risks, please re-synchronize them using one of the
following solutions:

  • Merge origin/development/8.3 into bugfix/ARSN-560-error-with-date-before-epoch
  • Rebase bugfix/ARSN-560-error-with-date-before-epoch onto origin/development/8.3

Note: If you choose to rebase, you may have to ask me to rebuild
integration branches using the reset command.

@leif-scality leif-scality changed the base branch from development/8.3 to development/8.2 March 24, 2026 11:52
@bert-e
Copy link
Contributor

bert-e commented Mar 24, 2026

Incorrect fix version

The Fix Version/s in issue ARSN-560 contains:

  • None

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 8.2.48

  • 8.3.8

Please check the Fix Version/s of ARSN-560, or the target
branch of this pull request.

@leif-scality leif-scality force-pushed the bugfix/ARSN-560-error-with-date-before-epoch branch 2 times, most recently from c30114c to 8f6cb9f Compare March 24, 2026 11:58
@scality scality deleted a comment from claude bot Mar 24, 2026
@scality scality deleted a comment from claude bot Mar 24, 2026
@scality scality deleted a comment from claude bot Mar 24, 2026
@scality scality deleted a comment from claude bot Mar 24, 2026
@scality scality deleted a comment from claude bot Mar 24, 2026
@claude
Copy link

claude bot commented Mar 24, 2026

  • Bug: constants.requestExpirySeconds does not existlib/constants.ts has no such export. At runtime this will be undefined, causing checkTimeSkew to never reject expired signatures. Either add the constant to lib/constants.ts or restore the inline 15 * 60.
    - Naming: ParseISO8601Compact uses PascalCase — inconsistent with all other functions in timeUtils.ts. Use parseISO8601Compact (and update all call sites).
    - Dead code: unreachable Number.isNaN check in timeUtils.ts:117 — if toISOString() succeeded, the date is valid. Remove the block.
    - Typo: extra space in return date; at timeUtils.ts:121.

    Review by Claude Code

@leif-scality leif-scality force-pushed the bugfix/ARSN-560-error-with-date-before-epoch branch from 8f6cb9f to ed3fa7a Compare March 24, 2026 12:05
@claude
Copy link

claude bot commented Mar 24, 2026

  • queryAuthCheck.ts may have the same pre-epoch timestamp vulnerability — it only checks timestamp length, not whether the date is before Unix epoch. Consider a follow-up fix there too.

    Review by Claude Code

@leif-scality leif-scality force-pushed the bugfix/ARSN-560-error-with-date-before-epoch branch from ed3fa7a to 4c683ec Compare March 24, 2026 12:08
@claude
Copy link

claude bot commented Mar 24, 2026

  • The pre-epoch guard added in headerAuthCheck.ts (line 108) is not mirrored in queryAuthCheck.ts, which uses the same convertAmzTimeToMs / validateCredentials flow. Pre-epoch timestamps in query-string auth could hit the same RequestTimeTooSkewed-instead-of-AccessDenied bug.
    - Add the same pre-epoch check in queryAuthCheck.ts, or extract the timestamp parsing + epoch check into a shared helper used by both auth paths.

    Review by Claude Code

'x-amz-date header') };
return {
err: errorInstances.AccessDenied.
customizeDescription('Authentication requires a valid Date or ' + 'x-amz-date header')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
customizeDescription('Authentication requires a valid Date or ' + 'x-amz-date header')
customizeDescription('Authentication requires a valid Date or x-amz-date header')

@leif-scality leif-scality requested a review from fredmnl March 24, 2026 19:31
@leif-scality leif-scality force-pushed the bugfix/ARSN-560-error-with-date-before-epoch branch from 4c683ec to 362f790 Compare March 25, 2026 10:30
@leif-scality
Copy link
Contributor Author

ping

@claude
Copy link

claude bot commented Mar 25, 2026

LGTM

The pre-epoch guard in headerAuthCheck.ts correctly rejects negative timestamps across all three input paths (x-amz-date compact, date compact, date UTC-converted). The parseISO8601Compact refactor is clean and not a breaking change since it was never part of the public API.

Minor note for follow-up: queryAuthCheck.ts has the same pre-existing pre-epoch gap (no guard before reaching validateCredentials/checkTimeSkew), which could produce RequestTimeTooSkewed instead of AccessDenied for pre-epoch query string auth requests.

Review by Claude Code

@leif-scality
Copy link
Contributor Author

ping

@bert-e
Copy link
Contributor

bert-e commented Mar 25, 2026

Request integration branches

Waiting for integration branch creation to be requested by the user.

To request integration branches, please comment on this pull request with the following command:

/create_integration_branches

Alternatively, the /approve and /create_pull_requests commands will automatically
create the integration branches.

@leif-scality
Copy link
Contributor Author

/create_integration_branches

@bert-e
Copy link
Contributor

bert-e commented Mar 25, 2026

Conflict

A conflict has been raised during the creation of
integration branch w/8.3/bugfix/ARSN-560-error-with-date-before-epoch with contents from bugfix/ARSN-560-error-with-date-before-epoch
and development/8.3.

I have not created the integration branch.

Here are the steps to resolve this conflict:

 git fetch
 git checkout -B w/8.3/bugfix/ARSN-560-error-with-date-before-epoch origin/development/8.3
 git merge origin/bugfix/ARSN-560-error-with-date-before-epoch
 # <intense conflict resolution>
 git commit
 git push -u origin w/8.3/bugfix/ARSN-560-error-with-date-before-epoch

The following options are set: create_integration_branches

@leif-scality
Copy link
Contributor Author

/create_pull_requests

@bert-e
Copy link
Contributor

bert-e commented Mar 25, 2026

Integration data created

I have created the integration data for the additional destination branches.

The following branches will NOT be impacted:

  • development/6.4
  • development/7.10
  • development/7.4
  • development/7.70
  • development/8.1

Follow integration pull requests if you would like to be notified of
build statuses by email.

The following options are set: create_pull_requests, create_integration_branches

@bert-e
Copy link
Contributor

bert-e commented Mar 25, 2026

Waiting for approval

The following approvals are needed before I can proceed with the merge:

  • the author

  • 2 peers

The following options are set: create_pull_requests, create_integration_branches

@leif-scality
Copy link
Contributor Author

/approve

@bert-e
Copy link
Contributor

bert-e commented Mar 25, 2026

I have successfully merged the changeset of this pull request
into targetted development branches:

  • ✔️ development/8.2

  • ✔️ development/8.3

The following branches have NOT changed:

  • development/6.4
  • development/7.10
  • development/7.4
  • development/7.70
  • development/8.1

Please check the status of the associated issue ARSN-560.

Goodbye leif-scality.

The following options are set: approve, create_pull_requests, create_integration_branches

@bert-e bert-e merged commit 362f790 into development/8.2 Mar 25, 2026
8 checks passed
@bert-e bert-e deleted the bugfix/ARSN-560-error-with-date-before-epoch branch March 25, 2026 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants