Skip to content

refactor: call the access token hash secret a pepper, not a salt - #2159

Merged
netomi merged 1 commit into
mainfrom
refactor/token-hash-pepper
Sep 4, 2026
Merged

netomi merged 1 commit into
mainfrom
refactor/token-hash-pepper

Conversation

@netomi

@netomi netomi commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

ovsx.access-token.token-hash-salt has every property of a pepper and none of a salt:

Salt Pepper This value
Scope unique per record one per instance one per instance
Storage stored next to the hash kept out of the datastore config only
Secret? no yes yes

The name misleads in a way that matters. A reader looking for the per-token salt column will not find one, and — worse — may take the value for the non-secret a salt is and put it somewhere a salt could legitimately go, such as a plain ConfigMap or a committed application.yml.

A salt would also have nothing to do here. Token values are 256 bits from a CSPRNG (AccessTokenService.java:67-83), so there is no dictionary to precompute against and no realistic chance of two hashing alike. The one thing this value buys is the pepper property: that a leaked personal_access_token.value column is useless without the configuration. The old javadoc gave it away too — a changed value invalidating every existing token is pepper rotation, since a per-record salt stays with its row.

Changes

  • ovsx.access-token.token-hash-salt → ovsx.access-token.token-hash-pepper
  • tokenHashSalt → tokenHashPepper, getTokenHashSalt() → getTokenHashPepper(), and the validate() failure message
  • Javadoc now says why it is a pepper, and keeps the rotation warning reframed as the pepper property it is
  • Call site and comment in AccessTokenService.hashTokenValue, plus the mock stub and one comment in AccessTokenServiceTest

No behaviour change: the hash construction is untouched.

No back-compat alias needed

The property has never shipped. It arrived in d5a01c8 (Trusted Publishing, #2000) on 2026-08-21, one day after the v1.1.2 release — git show v1.1.2:.../AccessTokenConfig.java has no trace of it. So unlike ovsx.access-token.prefix, which carries a fallback to its old ovsx.token-prefix key, this one needs none. Renaming after the next release would mean carrying that alias forever.

Verification

  • compileJava compileTestJava clean
  • ./gradlew test --tests '*AccessToken*' — 30 tests pass (AccessTokenServiceTest, plus the AdminAPITest and TrustedPublishingAPITest cases that exercise token creation and hashing end to end)
  • spotlessCheck reports no violations in the three touched files (it fails overall on pre-existing formatting under json/, untouched here)

Follow-ups, not in this PR

  • Rotating the pepper still invalidates every token, because the raw value is never stored and so no row can be rehashed. A pepper keyring with lazy rehash on use would fix that; PR to follow.
  • The pepper is applied as H(token || pepper) rather than HMAC(pepper, token). Not practically exploitable — the attacker controls no part of the input and length extension neither recovers the pepper nor forges a chosen token's hash — and changing it would break every stored hash, so it is deliberately left alone.

🤖 Generated with Claude Code

The value under ovsx.access-token.token-hash-salt has every property of
a pepper and none of a salt: one value for the whole instance rather
than one per token, secret, and deliberately kept out of the database
alongside the hashes it protects.

The name misleads in a way that matters. A reader looking for the
per-token salt column will not find one, and, worse, may take the value
for the non-secret a salt is and put it where a salt could legitimately
go - a plain ConfigMap, or a committed application.yml.

A salt would also have nothing to do here. Token values are 256 bits
from a CSPRNG, so there is no dictionary to precompute against and no
realistic chance of two hashing alike; the one thing this value buys is
the pepper property, that a leaked personal_access_token.value column is
useless without the configuration. The javadoc's own warning gives it
away too - a changed value invalidating every existing token is pepper
rotation, since a per-record salt stays with its row.

Renamed now because the property has never shipped: it arrived in
d5a01c8, one day after v1.1.2, so unlike ovsx.access-token.prefix it
needs no fallback to an old key.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@netomi
netomi requested review from cstamas and a lite review from Copilot September 4, 2026 08:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The change is a consistent rename across config/service/tests with no remaining references to the old key or getter found in the repository.

Pull request overview

Renames the access-token hash secret configuration from “salt” terminology to “pepper” to better reflect its instance-wide, secret, config-only role and reduce the risk of unsafe handling or misunderstanding.

Changes:

  • Rename config key ovsx.access-token.token-hash-salt → ovsx.access-token.token-hash-pepper and corresponding field/getter names.
  • Update AccessTokenService.hashTokenValue call site and clarify the inline comment.
  • Update tests and Javadoc to use “pepper” terminology and explain the security/rotation implications.
File summaries
File Description
server/src/main/java/org/eclipse/openvsx/accesstoken/AccessTokenConfig.java Renames property/field/getter and updates Javadoc + validation message to “pepper”.
server/src/main/java/org/eclipse/openvsx/accesstoken/AccessTokenService.java Switches the hash input from getTokenHashSalt() to getTokenHashPepper() and updates the comment.
server/src/test/java/org/eclipse/openvsx/accesstoken/AccessTokenServiceTest.java Updates mocks and comments to reflect “pepper” terminology.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@netomi
netomi merged commit 76e7397 into main Sep 4, 2026
6 checks passed
@netomi
netomi deleted the refactor/token-hash-pepper branch September 4, 2026 11:33
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.

3 participants