Skip to content

fix(security): replace timing-unsafe token comparisons with hmac.Equal#426

Merged
Alan-TheGentleman merged 2 commits into
mainfrom
fix/constant-time-token-compare
May 27, 2026
Merged

fix(security): replace timing-unsafe token comparisons with hmac.Equal#426
Alan-TheGentleman merged 2 commits into
mainfrom
fix/constant-time-token-compare

Conversation

@Alan-TheGentleman

Copy link
Copy Markdown
Collaborator

Summary

Replaces timing-unsafe ==/!= bearer and admin token comparisons with hmac.Equal([]byte(a), []byte(b)) (constant-time), eliminating the timing oracle. Fixes the three sites in #350 plus one additional matching site in authorizeDashboardRequest. Adds the crypto/hmac import to cloudserver.go.

Test plan

  • TestAuthorizeBearerTokenConstantTimeComparison (auth), TestValidateLoginTokenAdminComparisonGuard and TestIsDashboardAdminComparisonGuard (cloudserver): accept/reject correctness at each site
  • go test ./... && go vet ./... && go build ./... clean

Closes #350

Bearer and admin token comparisons used plain == / != operators, which are
not constant-time and leak timing information via early-exit string comparison.
Replace all four comparison sites with hmac.Equal([]byte(a), []byte(b)) as
required by issue #350. Add correctness guard tests for each site to ensure
accept/reject behavior is preserved.
Copilot AI review requested due to automatic review settings May 27, 2026 14:43
@Alan-TheGentleman Alan-TheGentleman added the type:bug Bug fix label May 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens Engram’s cloud authentication by replacing timing-unsafe string token comparisons (==/!=) with constant-time comparisons via crypto/hmac.Equal, reducing timing-oracle risk across bearer/admin token checks in the cloud surface.

Changes:

  • Replace bearer token comparison in internal/cloud/auth with hmac.Equal.
  • Replace dashboard admin token comparisons in internal/cloud/cloudserver (login, session auth, admin check) with hmac.Equal.
  • Add targeted regression tests to preserve accept/reject behavior at each modified comparison site.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
internal/cloud/cloudserver/cloudserver.go Uses hmac.Equal for admin token checks (login/session/admin) and adds crypto/hmac import.
internal/cloud/cloudserver/cloudserver_test.go Adds regression tests ensuring correct admin token behavior remains unchanged after switching comparisons.
internal/cloud/auth/auth.go Uses hmac.Equal for bearer token validation to avoid timing-unsafe comparisons.
internal/cloud/auth/auth_test.go Adds regression test covering accept/reject behavior (including prefix/superset cases) for bearer token comparison.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

// TestValidateLoginTokenAdminComparisonGuard is a correctness guard for the
// constant-time admin token comparison inside validateLoginToken (cloudserver.go:160).
}

// TestIsDashboardAdminComparisonGuard is a correctness guard for the
// constant-time admin token comparison inside isDashboardAdmin (cloudserver.go:320).
Comment on lines +256 to +258
// constant-time token comparison at auth.go:253. A correct token must be accepted
// and any wrong token must be rejected, preserving behavior after the
// timing-safe hmac.Equal replacement (security issue #350).
@Alan-TheGentleman Alan-TheGentleman merged commit a13915a into main May 27, 2026
5 checks passed
@Alan-TheGentleman Alan-TheGentleman deleted the fix/constant-time-token-compare branch May 27, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(cloud/auth): use constant-time compare for bearer token

2 participants