Skip to content

Comments

feat: no eip-712 verify#469

Open
philanton wants to merge 2 commits intomainfrom
feat/no-verify
Open

feat: no eip-712 verify#469
philanton wants to merge 2 commits intomainfrom
feat/no-verify

Conversation

@philanton
Copy link
Contributor

@philanton philanton commented Dec 18, 2025

Summary by CodeRabbit

  • Bug Fixes
    • Simplified signature verification flow in authentication and signing — the system now uses the provided challenge address as the signer and continues challenge validation and session issuance as before.
    • No changes to public interfaces or function signatures; core authentication and token issuance behavior remains intact.

✏️ Tip: You can customize this high-level summary in your review settings.

@philanton philanton requested a review from a team as a code owner December 18, 2025 10:43
@philanton philanton added invalid This doesn't seem right wip draft labels Dec 18, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Two functions were altered to bypass EIP-712 signature verification: RecoverAddressFromEip712Signature in clearnode/signer.go now returns the provided wallet address without recovering or validating the signer, and the RPC auth flow in clearnode/rpc_router_auth.go now uses the challenge's address instead of performing signature recovery.

Changes

Cohort / File(s) Summary
Signature Recovery Bypass
clearnode/signer.go
RecoverAddressFromEip712Signature no longer derives or uses typedDataHash, does not adjust v, does not call SigToPub, and does not derive the address from the signature. The function returns the input walletAddress directly. convertAllowances left unchanged.
RPC Auth: Skip Signature Verification
clearnode/rpc_router_auth.go
Replaced EIP-712 signature recovery with a direct assignment of recoveredAddress = challenge.Address, removing the error path and recovery-based validation. Subsequent ValidateChallenge, user tag creation, JWT issuance, and session handling remain unchanged.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas requiring attention:
    • Security implications of bypassing signature verification in both the signer and RPC auth flow.
    • Whether alternative validation mechanisms are present and sufficient.
    • Call sites and authentication flow relying on recovered addresses.
    • Test coverage and updating or adding tests to reflect removed verification.

Poem

A rabbit polishes a key so bright,
It finds the lock now open—light! 🐇🔑
The signature walked out the door,
The address sits, unproved, as before.
Mind the gap where trust should be, dear friend.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: disabling EIP-712 signature verification in the codebase by removing recovery logic.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/no-verify

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @philanton, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant change by disabling the EIP-712 signature verification mechanism within a core function. Instead of recovering a signer's address from a signature, the system will now use a pre-provided wallet address. This streamlines the signing process by bypassing cryptographic verification steps for EIP-712. Additionally, minor updates to Go module dependencies have been included.

Highlights

  • EIP-712 Verification Disabled: The RecoverAddressFromEip712Signature function in clearnode/signer.go has been modified to no longer perform EIP-712 signature verification. The logic for hashing typed data, fixing the V value, and recovering the public key has been commented out, and the function now directly returns a pre-existing walletAddress.
  • Dependency Updates: The go.work.sum file has been updated to include new versions of github.com/stretchr/testify (v1.8.1) and go.uber.org/multierr (v1.10.0).

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Dec 18, 2025

Codecov Report

❌ Patch coverage is 66.66667% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
clearnode/rpc_router_auth.go 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request, titled 'feat: no eip-712 verify', completely removes the EIP-712 signature verification from the RecoverAddressFromEip712Signature function. Instead of verifying the signature and recovering the signer's address, the function now returns the walletAddress that is passed in as an argument. This introduces a critical security vulnerability, as it would allow any caller to bypass authentication and impersonate any user. My review contains a critical comment urging to revert this change to restore the security of the signature verification process.

Comment on lines +125 to +143
_, _, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return "", err
}

// 2. Fix V if needed (Ethereum uses 27/28, go-ethereum expects 0/1)
if sig[64] >= 27 {
sig[64] -= 27
}
// if sig[64] >= 27 {
// sig[64] -= 27
// }

// 3. Recover public key
pubKey, err := crypto.SigToPub(typedDataHash, sig)
if err != nil {
return "", err
}
// // 3. Recover public key
// pubKey, err := crypto.SigToPub(typedDataHash, sig)
// if err != nil {
// return "", err
// }

signerAddress := crypto.PubkeyToAddress(*pubKey)
// signerAddress := crypto.PubkeyToAddress(*pubKey)

return signerAddress.Hex(), nil
return walletAddress, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

This change completely disables EIP-712 signature verification. The function RecoverAddressFromEip712Signature now simply returns the walletAddress provided as an argument, without verifying the cryptographic signature. This introduces a critical security vulnerability as it allows any caller to impersonate any wallet address by simply providing it as an argument, completely bypassing the authentication mechanism.

The function's name is now dangerously misleading, as it no longer recovers an address from a signature. The corresponding test TestEIPSignature will still pass, but it is no longer testing signature recovery, making it ineffective.

If this change is intended for testing, it should be handled via mocking or build tags, not by altering production code in this way. This change must be reverted to restore signature verification.

Suggested change
_, _, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return "", err
}
// 2. Fix V if needed (Ethereum uses 27/28, go-ethereum expects 0/1)
if sig[64] >= 27 {
sig[64] -= 27
}
// if sig[64] >= 27 {
// sig[64] -= 27
// }
// 3. Recover public key
pubKey, err := crypto.SigToPub(typedDataHash, sig)
if err != nil {
return "", err
}
// // 3. Recover public key
// pubKey, err := crypto.SigToPub(typedDataHash, sig)
// if err != nil {
// return "", err
// }
signerAddress := crypto.PubkeyToAddress(*pubKey)
// signerAddress := crypto.PubkeyToAddress(*pubKey)
return signerAddress.Hex(), nil
return walletAddress, nil
typedDataHash, _, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return "", err
}
// 2. Fix V if needed (Ethereum uses 27/28, go-ethereum expects 0/1)
if sig[64] >= 27 {
sig[64] -= 27
}
// 3. Recover public key
pubKey, err := crypto.SigToPub(typedDataHash, sig)
if err != nil {
return "", err
}
signerAddress := crypto.PubkeyToAddress(*pubKey)
return signerAddress.Hex(), nil

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0f48e8 and cb97f8d.

⛔ Files ignored due to path filters (1)
  • go.work.sum is excluded by !**/*.sum
📒 Files selected for processing (1)
  • clearnode/signer.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build and Publish (Clearnode)
  • GitHub Check: Test (Integration) / Test Integration
  • GitHub Check: Analyze (go)

Comment on lines +125 to +143
_, _, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return "", err
}

// 2. Fix V if needed (Ethereum uses 27/28, go-ethereum expects 0/1)
if sig[64] >= 27 {
sig[64] -= 27
}
// if sig[64] >= 27 {
// sig[64] -= 27
// }

// 3. Recover public key
pubKey, err := crypto.SigToPub(typedDataHash, sig)
if err != nil {
return "", err
}
// // 3. Recover public key
// pubKey, err := crypto.SigToPub(typedDataHash, sig)
// if err != nil {
// return "", err
// }

signerAddress := crypto.PubkeyToAddress(*pubKey)
// signerAddress := crypto.PubkeyToAddress(*pubKey)

return signerAddress.Hex(), nil
return walletAddress, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical security vulnerability: Signature verification completely disabled.

This change removes all cryptographic verification from RecoverAddressFromEip712Signature. The function now returns the provided walletAddress without validating the signature, allowing anyone to impersonate any wallet address.

Specific issues:

  1. typedDataHash from TypedDataAndHash is discarded (line 125)
  2. V value normalization commented out (lines 131-133)
  3. Public key recovery via SigToPub commented out (lines 135-139)
  4. Signer address derivation commented out (line 141)
  5. The sig parameter is now completely unused

This bypasses authentication entirely—an attacker can claim any wallet address without proving ownership. Even for testing/WIP purposes, this pattern is dangerous as it could accidentally reach production.

If verification needs to be optional for development, consider using a build tag or environment variable with explicit safeguards, rather than commenting out the core security logic.

🔎 Restore signature verification:
 	// 1. Hash the typed data (domain separator + message struct hash)
-	_, _, err := apitypes.TypedDataAndHash(typedData)
+	_, typedDataHash, err := apitypes.TypedDataAndHash(typedData)
 	if err != nil {
 		return "", err
 	}

 	// 2. Fix V if needed (Ethereum uses 27/28, go-ethereum expects 0/1)
-	// if sig[64] >= 27 {
-	// 	sig[64] -= 27
-	// }
+	if sig[64] >= 27 {
+		sig[64] -= 27
+	}

-	// // 3. Recover public key
-	// pubKey, err := crypto.SigToPub(typedDataHash, sig)
-	// if err != nil {
-	// 	return "", err
-	// }
+	// 3. Recover public key
+	pubKey, err := crypto.SigToPub(typedDataHash, sig)
+	if err != nil {
+		return "", err
+	}

-	// signerAddress := crypto.PubkeyToAddress(*pubKey)
+	signerAddress := crypto.PubkeyToAddress(*pubKey)

-	return walletAddress, nil
+	return signerAddress.Hex(), nil
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_, _, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return "", err
}
// 2. Fix V if needed (Ethereum uses 27/28, go-ethereum expects 0/1)
if sig[64] >= 27 {
sig[64] -= 27
}
// if sig[64] >= 27 {
// sig[64] -= 27
// }
// 3. Recover public key
pubKey, err := crypto.SigToPub(typedDataHash, sig)
if err != nil {
return "", err
}
// // 3. Recover public key
// pubKey, err := crypto.SigToPub(typedDataHash, sig)
// if err != nil {
// return "", err
// }
signerAddress := crypto.PubkeyToAddress(*pubKey)
// signerAddress := crypto.PubkeyToAddress(*pubKey)
return signerAddress.Hex(), nil
return walletAddress, nil
_, typedDataHash, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return "", err
}
// 2. Fix V if needed (Ethereum uses 27/28, go-ethereum expects 0/1)
if sig[64] >= 27 {
sig[64] -= 27
}
// 3. Recover public key
pubKey, err := crypto.SigToPub(typedDataHash, sig)
if err != nil {
return "", err
}
signerAddress := crypto.PubkeyToAddress(*pubKey)
return signerAddress.Hex(), nil
🤖 Prompt for AI Agents
In clearnode/signer.go around lines 125 to 143, signature verification was
removed causing the function to always return the provided walletAddress;
restore verification by capturing the typedDataHash from
apitypes.TypedDataAndHash, ensure sig is normalized (if sig[64] >= 27 subtract
27), call crypto.SigToPub with the typedDataHash and sig to recover the public
key, derive the signer address via crypto.PubkeyToAddress and compare it to the
provided walletAddress, returning an error when they don't match; preserve
proper error returns on each failure and, if an optional bypass is desired for
development only, gate it behind a clear build tag or environment flag rather
than commenting out verification.

Comment on lines +131 to +133
// if sig[64] >= 27 {
// sig[64] -= 27
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// if sig[64] >= 27 {
// sig[64] -= 27
// }

Comment on lines +135 to +139
// // 3. Recover public key
// pubKey, err := crypto.SigToPub(typedDataHash, sig)
// if err != nil {
// return "", err
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// // 3. Recover public key
// pubKey, err := crypto.SigToPub(typedDataHash, sig)
// if err != nil {
// return "", err
// }

// }

signerAddress := crypto.PubkeyToAddress(*pubKey)
// signerAddress := crypto.PubkeyToAddress(*pubKey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// signerAddress := crypto.PubkeyToAddress(*pubKey)

Copy link
Contributor

@alessio alessio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor remark: I'd get rid of unused code rather than commenting it out. Looks good otherwise

Copy link
Contributor

@alessio alessio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking to prevent merge

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb97f8d and 7afb8b2.

⛔ Files ignored due to path filters (1)
  • go.work.sum is excluded by !**/*.sum
📒 Files selected for processing (1)
  • clearnode/rpc_router_auth.go (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: dimast-x
Repo: erc7824/nitrolite PR: 419
File: clearnode/rpc_router_private.go:827-834
Timestamp: 2025-11-07T14:03:35.378Z
Learning: For the `revoke_session_key` RPC endpoint in clearnode/rpc_router_private.go: The design intentionally allows non-deterministic behavior when multiple session key signatures are present. Client-side code must ensure correct signatures are provided. The server keeps the RPC protocol flexible rather than implementing deterministic signature selection logic.
📚 Learning: 2025-11-07T14:03:35.378Z
Learnt from: dimast-x
Repo: erc7824/nitrolite PR: 419
File: clearnode/rpc_router_private.go:827-834
Timestamp: 2025-11-07T14:03:35.378Z
Learning: For the `revoke_session_key` RPC endpoint in clearnode/rpc_router_private.go: The design intentionally allows non-deterministic behavior when multiple session key signatures are present. Client-side code must ensure correct signatures are provided. The server keeps the RPC protocol flexible rather than implementing deterministic signature selection logic.

Applied to files:

  • clearnode/rpc_router_auth.go
📚 Learning: 2025-11-13T10:32:14.541Z
Learnt from: nksazonov
Repo: erc7824/nitrolite PR: 428
File: clearnode/rpc_router_auth.go:233-244
Timestamp: 2025-11-13T10:32:14.541Z
Learning: In clearnode/rpc_router_auth.go, when CheckSessionKeyExists returns ErrSessionKeyExistsAndExpired during authentication, the error should be returned to the client and block re-authentication. This is intentional behavior - expired session keys should not allow automatic re-authentication and replacement in the auth flow.

Applied to files:

  • clearnode/rpc_router_auth.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build and Publish (Clearnode)
  • GitHub Check: Test (Integration) / Test Integration
  • GitHub Check: Analyze (go)

Comment on lines +195 to +208
// recoveredAddress, err := RecoverAddressFromEip712Signature(
// challenge.Address,
// challenge.Token.String(),
// challenge.SessionKey,
// challenge.Application,
// challenge.Allowances,
// challenge.Scope,
// challenge.SessionKeyExpiresAt,
// sig)
// if err != nil {
// logger.Error("failed to recover address from signature", "error", err)
// return nil, nil, RPCErrorf("invalid signature")
// }
recoveredAddress := challenge.Address // TODO: implement EIP-712 signature recovery
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical security vulnerability: Authentication bypass allows any user to impersonate any wallet.

By assigning recoveredAddress := challenge.Address, the signature verification is completely disabled. The sig parameter is accepted but never validated, meaning:

  1. Any client can authenticate as any wallet address without proving key ownership
  2. An attacker only needs to know a target wallet address to impersonate it
  3. The entire authentication security model is broken

Even for development/testing purposes, this approach is dangerous because:

  • The code could accidentally be merged to production
  • There's no build-time or runtime guard preventing this from running in production environments

If this is intended for local development only, consider using a build tag or environment-based feature flag:

🔎 Suggested safer approach for development bypass:
-	// recoveredAddress, err := RecoverAddressFromEip712Signature(
-	// 	challenge.Address,
-	// 	challenge.Token.String(),
-	// 	challenge.SessionKey,
-	// 	challenge.Application,
-	// 	challenge.Allowances,
-	// 	challenge.Scope,
-	// 	challenge.SessionKeyExpiresAt,
-	// 	sig)
-	// if err != nil {
-	// 	logger.Error("failed to recover address from signature", "error", err)
-	// 	return nil, nil, RPCErrorf("invalid signature")
-	// }
-	recoveredAddress := challenge.Address // TODO: implement EIP-712 signature recovery
+	recoveredAddress, err := RecoverAddressFromEip712Signature(
+		challenge.Address,
+		challenge.Token.String(),
+		challenge.SessionKey,
+		challenge.Application,
+		challenge.Allowances,
+		challenge.Scope,
+		challenge.SessionKeyExpiresAt,
+		sig)
+	if err != nil {
+		logger.Error("failed to recover address from signature", "error", err)
+		return nil, nil, RPCErrorf("invalid signature")
+	}

If you need a dev-only bypass, use a separate file with //go:build dev or check an explicit environment variable like DISABLE_SIG_VERIFY=true with prominent logging warnings.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// recoveredAddress, err := RecoverAddressFromEip712Signature(
// challenge.Address,
// challenge.Token.String(),
// challenge.SessionKey,
// challenge.Application,
// challenge.Allowances,
// challenge.Scope,
// challenge.SessionKeyExpiresAt,
// sig)
// if err != nil {
// logger.Error("failed to recover address from signature", "error", err)
// return nil, nil, RPCErrorf("invalid signature")
// }
recoveredAddress := challenge.Address // TODO: implement EIP-712 signature recovery
recoveredAddress, err := RecoverAddressFromEip712Signature(
challenge.Address,
challenge.Token.String(),
challenge.SessionKey,
challenge.Application,
challenge.Allowances,
challenge.Scope,
challenge.SessionKeyExpiresAt,
sig)
if err != nil {
logger.Error("failed to recover address from signature", "error", err)
return nil, nil, RPCErrorf("invalid signature")
}

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

Labels

draft invalid This doesn't seem right wip

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants