Skip to content

fix(express): require auth token for external signer mode - #9452

Closed
0xroyce wants to merge 1 commit into
BitGo:masterfrom
0xroyce:fix/express-signer-mode-auth
Closed

fix(express): require auth token for external signer mode#9452
0xroyce wants to merge 1 commit into
BitGo:masterfrom
0xroyce:fix/express-signer-mode-auth

Conversation

@0xroyce

@0xroyce 0xroyce commented Aug 7, 2026

Copy link
Copy Markdown

Summary

  • Security fix (CWE-306): BitGo Express --signerMode previously mounted /api/v2/{coin}/sign, TSS share, and OFC external sign routes behind prepareBitGo only, which never rejects a missing Authorization header. Any network client that could reach the signer port could use disk-held user keys as an unauthenticated signing oracle.
  • Fix: Require signerAuthToken (--signerAuthToken / BITGO_SIGNER_AUTH_TOKEN) whenever signerMode or externalSignerUrl is configured. Signer routes now reject missing/wrong Bearer with HTTP 401 (timing-safe compare). Generator Express forwards the same token when calling externalSignerUrl.
  • Reported via whitehat research (Bugcrowd-ready write-up available). Demonstrated locally with researcher-owned key material only.

Breaking change / migration

Operators running external signing must set a shared secret on both the signer and generator Express instances, e.g.:

export BITGO_SIGNER_AUTH_TOKEN='<high-entropy-secret>'
# signer:
bitgo-express --signerMode --signerFileSystemPath ./keys.json --signerAuthToken "$BITGO_SIGNER_AUTH_TOKEN"
# generator:
bitgo-express --externalSignerUrl https://signer.example --signerAuthToken "$BITGO_SIGNER_AUTH_TOKEN"

Test plan

  • Unit: unauthenticated /api/v2/tbtc/sign → 401
  • Unit: wrong Bearer → 401
  • Unit: correct Bearer still signs (existing coinSign coverage)
  • Unit: startup without signerAuthToken in signerMode throws ExternalSignerConfigError
  • CI full express unit + integration suite

Close the CWE-306 gap where signerMode routes accepted unauthenticated
sign/TSS/OFC requests against disk-held user keys. Require
BITGO_SIGNER_AUTH_TOKEN/--signerAuthToken at startup and validate Bearer
on signer routes; forward the token from generator Express to externalSignerUrl.
@0xroyce
0xroyce requested review from a team as code owners August 7, 2026 19:29
@0xroyce

0xroyce commented Aug 7, 2026

Copy link
Copy Markdown
Author

Reviewer note (external whitehat)

Validate Humans In The Loop fails because this commit is from an external researcher (@0xroyce) and is not signed by a BitGo allowlisted engineer. That is expected for an outside security fix.

Ask: @bitgo/wallet-core / @bitgo/wallet-core-india — please review + approve (CODEOWNERS needs 2). Happy to adjust the auth design (mTLS vs shared Bearer, rollout flags, docs) if you want a different migration path.

Why this should not wait on “silent discovery”: the broken behavior is already demonstrated (missing Authorization → sign). This PR is the patch. Leaving signerMode unauthenticated while the diff is public is worse than merging/hot-fixing quickly.

@0xroyce

0xroyce commented Aug 7, 2026

Copy link
Copy Markdown
Author

Closing this PR at researcher request.

We are revisiting disclosure packaging. The underlying finding (signerMode missing authentication) remains valid and will be handled via coordinated disclosure (Bugcrowd / BitGo security), not this public patch PR for now.

@0xroyce 0xroyce closed this Aug 7, 2026
@0xroyce
0xroyce deleted the fix/express-signer-mode-auth branch August 7, 2026 19: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