Skip to content

fix(security): harden analytics Basic Auth (fail-closed + constant-time)#261

Open
ttonyxx wants to merge 1 commit into
security/04-otp-send-rate-limitfrom
security/05-analytics-auth-hardening
Open

fix(security): harden analytics Basic Auth (fail-closed + constant-time)#261
ttonyxx wants to merge 1 commit into
security/04-otp-send-rate-limitfrom
security/05-analytics-auth-hardening

Conversation

@ttonyxx

@ttonyxx ttonyxx commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Severity: 🟡 Medium — potential open admin API + timing side-channel

Top of the stack — #260#259#258#257.

AnalyticsBasicAuth guards admin endpoints that can look up any user by email (/analytics/user/:email) and manually upgrade/downgrade accounts.

The problems

  1. Fail-open when unconfigured. It compared request creds directly to the env vars. If ANALYTICS_USERNAME/ANALYTICS_PASSWORD are empty/unset, a request with empty Basic Auth credentials matches → the admin API is wide open on a misconfigured deploy.
  2. Non-constant-time comparison (!=) on credentials leaks information via timing.

The fix

  • Fail closed: return 503 if either credential env var is unset.
  • Compare username & password with crypto/subtle.ConstantTimeCompare.

🤖 Generated with Claude Code

## Why this change is needed

`AnalyticsBasicAuth` protects admin endpoints that can look up any user by
email and manually upgrade/downgrade accounts. Two issues weakened it:

1. **Fail-open when unconfigured.** The check compared the request credentials
   directly against the env vars. If `ANALYTICS_USERNAME`/`ANALYTICS_PASSWORD`
   were unset (empty), a request presenting empty Basic Auth credentials would
   match and be granted access — turning a misconfiguration into an open admin
   API.
2. **Non-constant-time comparison.** Using `==` on the credentials can leak
   their length/contents through timing differences.

## What this does

- Refuses the request with `503` if either credential env var is unset, so the
  endpoints fail closed instead of open.
- Compares username and password with `crypto/subtle.ConstantTimeCompare`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ttonyxx ttonyxx force-pushed the security/04-otp-send-rate-limit branch from 5a50270 to 0bc149f Compare May 29, 2026 18:49
@ttonyxx ttonyxx force-pushed the security/05-analytics-auth-hardening branch from 2eaff2b to 5ec785f Compare May 29, 2026 18:49
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.

1 participant