ObolNetwork / ObolNetwork/obol-stack

Bind SIWX session tokens to origin/offer (audience claim)

Open
#828 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Go
Stars
11
Forks
1
PR merge metrics
No merged PRs in 30d

Description

Context

Filed for internal follow-up from an external security researcher report. Tracked here rather than via the bug bounty program, since obol-stack is out of the program's scope.

The SIWX one-shot EIP-4361 verification correctly binds the signed message to the request host (Authenticate / expectedDomain in internal/x402/siwx.go). However, the reusable session token minted afterwards does not carry that binding:

  • MintSession (internal/x402/siwx.go) signs siwxSessionClaims{ Wallet, Exp } with the per-process HMAC secret. There is no host, origin, or offer claim.
  • VerifySession checks only the HMAC signature and expiry, then returns the wallet.

Because a single verifier instance serves multiple routes/offers and can front multiple origins (see the shared-origin vs dedicated-hostname handling in internal/x402/authgate.go), a session token minted after signing in to one offer is accepted on another offer served by the same verifier, after which X-Verified-Wallet is injected for that wallet on the second offer. In a deployment where offers have differing trust levels, this permits cross-offer reuse of a session token (an audience-confusion weakness).

Scope note on blast radius: the session secret is generated per verifier process (NewSIWXAuthenticator -> crypto/rand), so a token never crosses separate verifier instances. The concern is confined to a single verifier instance that fronts more than one offer/origin.

Changes

  • Add an origin/offer (audience) claim to siwxSessionClaims in internal/x402/siwx.go.
  • Populate it at MintSession time from the verified request host/offer.
  • Enforce it in VerifySession, rejecting a token presented on an origin/offer other than the one it was minted for.
  • Add a regression test: a token minted for offer A is rejected when presented on offer B.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with internal/x402/siwx.go, tracing MintSession and VerifySession, then read the shared-origin and dedicated-hostname handling in internal/x402/authgate.go. Add the audience binding and a regression test showing that a token minted for offer A is rejected for offer B; run the existing internal/x402 tests to verify the behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
authentication, backend-api-design, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.