Skip to content

[CRITICAL] Auth bypass — SEP-10 signature verification missing #24

Closed

Description

@DeFiVC

Description

verifyChallenge in src/modules/auth/auth.service.ts:78 compares signedChallenge !== stored.challengeToken — a plain string comparison. It never decodes a Stellar transaction envelope, never verifies a cryptographic signature against the user's public key, and never checks time bounds.

Any client that echoes back the challenge token string passes authentication without needing a Stellar private key.

Impact

Complete authentication bypass — attackers can authenticate as any user without owning their Stellar key.

File

src/modules/auth/auth.service.ts:78

Suggested Fix

Replace string comparison with proper SEP-10 verification using the Stellar SDK:

  • Decode the transaction envelope
  • Verify the signature against the claimed public key
  • Check time bounds (challenge expiration)
  • Verify the source account matches

Activity

  1. AbelOsaretin commented on Jun 20, 2026

    @AbelOsaretin
    Contributor

    I'd like to work on this issue.
    The verifyChallenge method in src/modules/auth/auth.service.ts:78 uses a plain string comparison (signedChallenge !== stored.challengeToken) instead of proper cryptographic verification. This means any client that simply echoes back the challenge token string bypasses authentication entirely — no Stellar private key required. This is a complete authentication bypass that allows attackers to impersonate any user on the platform.
    My approach
    Replace the naive string comparison with proper SEP-10 signature verification using the Stellar SDK's built-in helpers. The fix will decode the transaction envelope, verify the cryptographic signature against the claimed public key, validate time bounds to prevent replay attacks, and confirm the source account matches the authenticated user.
    Implementation plan

    1. Import Stellar SDK verification utilities
      • Add Transaction and TransactionBuilder imports from stellar-sdk
      • Add Keypair import for public key verification
      • Add time-bound checking utilities (e.g., DateTime from luxon if already in deps, or native Date)
    2. Replace string comparison in verifyChallenge at line 78
      • Decode the signed challenge using Transaction.fromEnvelopeXDR() instead of comparing raw strings
      • Extract the signature from the decoded transaction using tx.signatures
      • Verify the signature matches the user's stored public key using Keypair.fromPublicKey(publicKey).verify(tx.hash(), signature)
      • Remove the signedChallenge !== stored.challengeToken comparison entirely
    3. Add time-bound validation
      • After decoding the transaction envelope, check tx.timeBounds.minTime and tx.timeBounds.maxTime
      • Reject challenges where now < minTime or now > maxTime to prevent stale/replay attacks
      • Use a reasonable expiration window (e.g., 5 minutes) matching SEP-10 best practices
    4. Verify source account matches
      • Confirm tx.source matches stored.publicKey (or the user's Stellar address from the database)
      • This prevents an attacker from using a legitimately signed SEP-10 challenge issued for a different account
    5. Update tests for the new verification logic
      • Add test cases for valid SEP-10 signed challenges (should pass authentication)
      • Add test cases for expired challenges (should be rejected)
      • Add test cases for challenges signed by a different key (should be rejected)
      • Add test cases for malformed/invalid XDR envelopes (should be rejected gracefully)
        Impact
    • Eliminates a complete authentication bypass that allows impersonation of any user without their private key.
    • Aligns the auth flow with the SEP-10 specification, the industry-standard authentication protocol for Stellar-based applications.
    • Prevents replay attacks through time-bound validation, ensuring stale challenges cannot be reused.
    • Establishes proper cryptographic verification as a foundation for all future auth-related features.
      I'm ready to start immediately and can have a PR up within a reasonable timeline. Happy to adjust the plan if you have preferences on any of the details.
  2. grantfox-oss commented on Jun 20, 2026

    @grantfox-oss

    🦊 GrantFox — @AbelOsaretin has been assigned to this issue as part of the Official Campaign campaign!

    Next steps:

    1. Open a Pull Request referencing this issue (e.g., Closes #24)
    2. Your PR will be reviewed by the ChainLearnOfficial maintainers

    Good luck! Track your progress on GrantFox.

  3. grantfox-oss commented on Jun 20, 2026

    @grantfox-oss

    🎉 This issue has been marked as completed on GrantFox as part of the Official Campaign campaign!

    @AbelOsaretin's PR #39 was approved and merged by @DeFiVC.

    🏆 @AbelOsaretin: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (223 total points). Track your full progress on GrantFox.

    👏 Great work, @AbelOsaretin! Keep contributing to ChainLearnOfficial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignbugSomething isn't workingcriticalsecuritySecurity concern

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions