Skip to content

Common: derive Hash.otp secrets from the app key - #19

Merged
3m1n3nc3 merged 1 commit into
mainfrom
fix/common-otp-secret
Oct 23, 2026
Merged

3m1n3nc3 merged 1 commit into
mainfrom
fix/common-otp-secret

Conversation

@3m1n3nc3

Copy link
Copy Markdown
Member

Problem

Hash.otp() built every code from one hardcoded TOTP secret (US3WHSG7X5KAPV27VANWKQHF3SH3HULL), and the label had no effect on the result. Within a period, every label got the same code, and anyone could compute it from the published package. Apps that use Hash.otp for password reset, email verification or emailed 2FA codes were open to account takeover.

Fix

Each label now gets its own secret: an HMAC-SHA256 of the label under APP_KEY. The method signature is unchanged. Hash.otp throws if no app key is configured.

Upgrade note

Codes issued before the upgrade stop validating once it is deployed.

Tests

packages/common/tests/hash.test.ts covers:

  • a code validates for its own label;
  • labels get different secrets, and one label's code does not validate for another;
  • the secret changes with APP_KEY;
  • the fixed secret is no longer used.

Hash.otp used one hardcoded TOTP secret for every label, so a code issued
for one account was valid for all of them and anyone could compute it from
the published package. Each label now gets its own secret, an HMAC of the
label under APP_KEY.
@codecov

codecov Bot commented Oct 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@3m1n3nc3
3m1n3nc3 merged commit 92c5610 into main Oct 23, 2026
4 checks passed
@3m1n3nc3
3m1n3nc3 deleted the fix/common-otp-secret branch October 23, 2026 03:01
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