Skip to content

security: add domain validation to SIWE authentication examples#1559

Open
cryptoasuran wants to merge 1 commit into
base:masterfrom
cryptoasuran:security/fix-siwe-domain-validation
Open

security: add domain validation to SIWE authentication examples#1559
cryptoasuran wants to merge 1 commit into
base:masterfrom
cryptoasuran:security/fix-siwe-domain-validation

Conversation

@cryptoasuran
Copy link
Copy Markdown

Summary

Fixes cross-domain replay attack vulnerability in the authenticate-users guide backend examples.

Problem (Issue #1502)

The current backend verification code only checks the cryptographic signature without validating the SIWE message domain:

const valid = await client.verifyMessage({ address, message, signature });

This is insecure. A valid SIWE signature created for evil.com can be submitted to yourapp.com's /auth/verify endpoint and will pass verification, because verifyMessage only validates the cryptographic signature — not whether the message was intended for this domain.

EIP-4361 Requirement

EIP-4361 explicitly requires relying parties to validate the domain field:

"The full SIWE message MUST be checked for conformance... checked against expected values after parsing (e.g., expiration-time, nonce, request-uri, domain etc.)"

Solution

Replace verifyMessage with verifySiweMessage which validates domain, nonce, and expiry:

import { verifySiweMessage } from 'viem/siwe';

const valid = await verifySiweMessage(client, {
  address,
  message,
  signature,
  domain: 'yourapp.com', // Validates message was intended for this domain
});

Changes

  • ✅ Updated both backend examples (inline + Express server)
  • ✅ Added verifySiweMessage import from viem/siwe
  • ✅ Added explicit domain parameter with comment
  • ✅ Added security rationale comment in Express example

Impact

Before: Developers following this guide ship authentication endpoints vulnerable to cross-domain replay attacks.

After: Secure authentication that complies with EIP-4361 spec.

Testing

Code follows viem's official API:

Fixes #1502

Fixes cross-domain replay attack vulnerability in authenticate-users guide.

## Problem
Backend examples only verified cryptographic signature without validating
the SIWE message domain. This allows valid signatures from evil.com to be
replayed against yourapp.com's /auth/verify endpoint.

## Changes
- Replace `verifyMessage` with `verifySiweMessage` in both examples
- Add explicit domain parameter validation
- Add comment explaining security rationale
- Import `verifySiweMessage` from 'viem/siwe'

## Impact
Prevents cross-domain replay attacks as required by EIP-4361 spec.
Developers following this guide will now ship secure authentication.

Fixes base#1502

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cb-heimdall
Copy link
Copy Markdown
Collaborator

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/2
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 1
Sum 2

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.

fix(docs): authenticate-users backend example missing domain validation — vulnerable to cross-domain replay attack

3 participants