Conversation
After removing server and clientSigningKey from signersFound, check if the array is empty and throw InvalidChallengeError. Previously, a malicious wallet operator controlling a client_domain key could authenticate as any user by signing only with the clientSigningKey. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace account-level flag constants with trustline-level bit values: - authorized: bit 0x1 (was coincidentally correct) - clawback: bit 0x4 (was 0x8, always returned false) - Replace revocable with authorizedToMaintainLiabilities: bit 0x2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Clear this.built before re-simulation after restore to prevent stale sequence number (tx_bad_seq) - Add !isSimulationRestore guard to prevent assembling transaction with incorrect resource data when restore=false - Wrap signTransaction callback instead of mutating shared options to prevent race condition on submit flag Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite request interceptor loop to use promise chaining (matching response interceptors) so async interceptors that return Promise<V> are properly resolved before using the config. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses a set of internal correctness and security bugs across WebAuth (SEP-10), Soroban RPC helpers, the fetch-based HTTP client, and contract transaction assembly/signing.
Changes:
- Harden SEP-10
verifyChallengeTxSignersto prevent aclient_domain-only signature from satisfying client signer requirements, and add regression coverage. - Fix trustline flag decoding in
rpc.Server#getAssetBalance, adjust the public response shape, and add unit coverage for clawback flag decoding. - Fix Soroban client behavior around simulation restoration (stale sequence / inappropriate assembly) and avoid shared-options mutation in
signAndSend; also ensure async fetch request interceptors are awaited.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/unit/utils.test.ts | Adds a regression test ensuring client_domain signatures don’t bypass client-signer verification. |
| src/webauth/challenge_transaction.ts | Enforces that at least one real client signer remains after excluding server and client_domain signer. |
| src/rpc/server.ts | Corrects trustline flag bitmask decoding in getAssetBalance. |
| src/rpc/api.ts | Updates BalanceResponse trustline flag field naming to match semantics. |
| test/unit/server/soroban/get_classic_entries.test.ts | Updates and extends tests to validate correct trustline flag decoding, including clawback. |
| src/http-client/fetch-client.ts | Refactors request interceptor execution to properly await async interceptors before dispatching. |
| src/contract/assembled_transaction.ts | Fixes restoration/simulation flow and prevents signAndSend from mutating shared options (race avoidance). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| authorized: boolean; | ||
| clawback: boolean; | ||
| revocable?: boolean; // only present for trustlines | ||
| authorizedToMaintainLiabilities?: boolean; // only present for trustlines |
There was a problem hiding this comment.
Renaming balanceEntry.revocable to authorizedToMaintainLiabilities is a breaking public API change (and revocable is referenced in the existing changelog entry for rpc.Api.BalanceResponse). If the intent is to correct semantics rather than introduce a new field, consider keeping revocable as a deprecated alias (or updating all public docs/changelog in the same PR) to avoid silently breaking downstream TypeScript consumers.
| authorizedToMaintainLiabilities?: boolean; // only present for trustlines | |
| authorizedToMaintainLiabilities?: boolean; // only present for trustlines | |
| /** @deprecated Use authorizedToMaintainLiabilities instead. */ | |
| revocable?: boolean; // legacy alias for trustlines |
|
Size Change: +34.6 kB (+0.08%) Total Size: 45.5 MB 📦 View Changed
|
What
This fixes a collective of bugs documented here
verifyChallengeTxSignersauthentication bypass with client_domaingetAssetBalanceAssembledTransaction.simulate