eth_sign and eth_signTypedData bypass AllowInsecureUnlock JSON-RPC gate

Open Beginner friendly
#4,607 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
go

Research direction

Read rpc/backend/sign_tx.go around Backend.Sign() and Backend.SignTypedData(), then inspect the AllowInsecureUnlock checks in the other account RPC methods. Add equivalent guards to both signing methods and unit tests for the false flag; done means both return the forbidden error when insecure unlock is disabled. The issue also points to an existing fix on origin/worktree-fix-eth-sign-insecure-unlock.

Written by the indexing model from the issue text.

Description

bug_bounty zetacore

Summary

eth_sign and eth_signTypedData in the JSON-RPC backend skip the AllowInsecureUnlock check that the other four account-related RPCs enforce. When an operator runs with --json-rpc.allow-insecure-unlock=false expecting account-related signing over HTTP to be blocked, these two endpoints still produce signatures from the loaded keyring.

Vulnerable code (on main HEAD 9a516a34d)

  • rpc/backend/sign_tx.go:124-142 — Backend.Sign() accesses b.ClientCtx.Keyring.SignByAddress with no AllowInsecureUnlock guard.
  • rpc/backend/sign_tx.go:147-168 — Backend.SignTypedData() same pattern, no guard.

For comparison, the correctly guarded endpoints all open with if !b.Cfg.JSONRPC.AllowInsecureUnlock { return ..., fmt.Errorf("account unlock with HTTP access is forbidden") }:

  • rpc/backend/sign_tx.go:22-27 — SendTransaction()
  • rpc/backend/node_info.go:34 — Accounts()
  • rpc/backend/node_info.go:84 — SetEtherbase()
  • rpc/backend/node_info.go:225 — ListAccounts()

Fix

A fix already exists on the remote branch origin/worktree-fix-eth-sign-insecure-unlock (commit d8ea64168, dated 2026-03-24) that adds the four-line guard to both functions. Merge that branch (or land an equivalent two-function patch) plus unit tests asserting the error response when the flag is false. Also worth adding a sweep test or linter check that asserts every Backend method touching b.ClientCtx.Keyring.Sign* either has the AllowInsecureUnlock guard or an explicit comment justifying why it does not, so the next account-related RPC we add does not repeat the omission.

Severity / impact

Classified as Low on HackenProof. eth_sign returns a \x19Ethereum Signed Message-prefixed signature only useful for off-chain auth flows; eth_signTypedData can produce EIP-712 signatures usable for ERC-2612 permit-drain or off-chain marketplace orders, but the realistic fund-extraction path requires four operator-side preconditions to converge (flag set to false against the default true, funded EVM key loaded into validator keyring against standard operator practice, EIP-712-eligible assets controlled by that key, and a publicly reachable RPC port). The realistic population on ZetaChain mainnet satisfying all four is plausibly zero. The fix ships as code hygiene rather than incident response.

Source

HackenProof report: https://dashboard.hackenproof.com/manager/companies/zetachain/zetachain-blockchain-software/reports/ZCNode-284

Dominant language
Go
Stars
202
Forks
181
Avg merge
17h 6m
Merged PRs (30d)
2

Getting set up

  • No Dockerfile or Docker Compose file
  • Has a pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from zeta-chain/node

All issues in zeta-chain/node

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.