fix(api): validate userId is a Stellar public key on notification routes - #18
Conversation
The notification subscribe, preferences, and unsubscribe endpoints accepted any non-empty string as userId, allowing invalid IDs to persist permanently in notification_preferences and breaking downstream consumers (auto-rebalancer portfolio lookups, Stellar signature verification) that assume userId is a valid Stellar account. Add a reusable `isValidStellarPublicKey` helper (and `stellarAddressSchema`) backed by the Stellar SDK's `StrKey.isValidEd25519PublicKey`, which checks length, alphabet, version byte and CRC16 checksum — stricter and more correct than a bare regex. Reject malformed userIds with HTTP 400 on all three routes. Closes grantFoxin#7
97ab3d3 to
0439c69
Compare
|
The StrKey explanation is spot on — the regex approach from the issue would have passed The type guard ( Two things worth a look before merge: The The tests cover the helper and schema in isolation which is thorough, but there's no HTTP-level test confirming the routes actually return 400 for a bad Overall this is clean — the core fix is correct and the route coverage is consistent across all three endpoints. |
Thanks for the thorough review — appreciate the detailed read. On the schema/helper split: the two aren't actually different validation On the integration test: agreed, that closes the loop. I'll add an HTTP-level |
Add integration tests asserting the notification subscribe, preferences, and unsubscribe routes return 400 for a malformed userId and accept a valid Stellar public key, closing the gap left by the helper/schema unit tests. Also document that stellarAddressSchema and isValidStellarPublicKey share the same validation logic, clarifying why the routes call the helper directly instead of parsing through the schema.
|
nice job @xeladev4 merging soon |
fix(api): validate userId is a Stellar public key on notification routes
Closes #7
Problem
POST /api/notifications/subscribe,GET /api/notifications/preferences, andDELETE /api/notifications/unsubscribeaccepted any non-empty string asuserIdwith no check that it is a valid Stellar public key. Invalid IDs werepersisted permanently in
notification_preferences, breaking downstreamfunctionality that assumes
userIdis a valid Stellar address:userIdon Stellar Horizon errors out, potentially halting a notification pass.
Keypair.fromPublicKey(userId)throws ona malformed address.
Stellar account.
Fix
isValidStellarPublicKey()helper andstellarAddressSchemain backend/src/api/validation.ts, backed by
the Stellar SDK's
StrKey.isValidEd25519PublicKey().userIdwith HTTP400on all three notification routes inbackend/src/api/routes.ts.
Why
StrKeyinstead of a regexThe originally proposed
^[GT][A-Z0-9]{54}$regex is not correct for Stellaraddresses:
A–Z,2–7) — the regex's0,1,8,9are never valid, while
2–7are missing.Tprefix is pre-auth transaction keys, not "testnet"; account publickeys always start with
Gregardless of network.keys would still pass.
StrKey.isValidEd25519PublicKey()validates length, alphabet, version byte andchecksum, so it correctly rejects malformed keys, secret seeds (
S…), andmuxed accounts (
M…).Tests
Added backend/src/test/stellarAddressValidation.test.ts
covering valid keys, arbitrary strings, bad checksums, secret seeds, and
non-string inputs.
npm run build(tsc) passes clean.Steps to verify