Geth’s insecure unlock

Clyde D'Cruz
4 min readOct 9, 2020

The Ethereum ecosystem is rapidly changing. Being open source software, a lot of improvements can pour in every year. A side effect of this is that “tutorial” and “quickstart” blogs can possibly get outdated, and leave readers confused. I was one such reader. In this article I’m going to describe an interesting error I ran into while trying to unlock an account with geth and the subsequent learning that ensued.

Photo by George Becker from Pexels

As per the tutorial I was following, I first started an Ethereum node using geth --ropsten --syncmode "light" --rpc --rpcaddr 127.0.0.1 . My intent was to start a “light” node on the Ropsten testnet and deploy a contract to it using Truffle. I then ran geth attach \\.\pipe\geth.ipc to connect to the Geth console via the IPC end point and tried to unlock an account which I would use to deploy the contract. Here Geth errored out with this message.

Error: account unlock with HTTP access is forbidden

At first this did not make complete sense because I was connected to the Ethereum node via IPC, not HTTP. So what is Geth complaining about?

I took a step back and had a closer look at the geth command that I used for starting the node. geth --help (sounds like a pun :D) easily revealed explanations for each of the options I had used.

--rpc            Enable the HTTP-RPC server (deprecated, use --http)
--ropsten Ropsten network: pre-configured proof-of-work test network
--rpcaddr value HTTP-RPC server listening interface (deprecated, use --http.addr) (default: "localhost")

As the help page says, the --rpc option enables the Ethereum node’s HTTP-RPC server. What is this HTTP-RPC server and what is it used for?

This server is an HTTP endpoint that enables Javascript applications to talk to an Ethereum node using the JSON-RPC protocol. We can use libraries like web3.js and web3.py to programatically interact with an Ethereum node over this protocol.

Back to our error — Why is account unlock forbidden when the HTTP server is enabled?

If an Ethereum account is unlocked and the HTTP interface is exposed to the outside world (i.e. on the host’s public network interface) then it is possible for anyone to transfer funds from your account or sign a transaction using your account’s key. In 2018 there were reports of a massive campaign by attackers that scanned for internet-exposed Ethereum wallets and mining equipment. Also common, was to have accounts mysteriously emptied by bots soon after they were unlocked.

To mitigate this potential vulnerability a change was introduced in Geth to disallow unlocking accounts when the HTTP or websockets interface is enabled. This comment in the pull request describes how Geth can be expected to behave at present. However it’s still possible to unlock accounts whilst exposing the HTTP or Websockets interfaces by explicitly providing the --allow-insecure-unlock option to geth. This must be used with great caution.

Its worth noting that by default the geth node doesn’t start the HTTP and WebSocket servers. And even when they are explicitly started using the --http and --ws flags, not all functionality is provided over these interfaces for security reasons. These defaults can be overridden with the --rpcapi and --wsapi arguments, or with admin.startRPC() and admin.startWS().

Best practices when using accounts

  • Do not enable the RPC or WebSockets interfaces when doing operations on Geth that require an unlocked account. You can use the IPC endpoint for attaching to the interactive javascript console. For e.g. you can start a light node on the ropsten testnet using geth --ropsten --syncmode "light". The node prints the IPC endoint address in the logs on startup. You can then attach to the IPC endpoint using geth attach path/to/ipc/geth.ipc
  • When using the CLI, it is recommended to do the account unlock interactively as opposed to specifying the password directly as part of the command. For e.g. The following command starts a node on the Ropsten testnet with the specified account unlocked. The HTTP-RPC and Websockets interfaces are not enabled.
geth --ropsten --syncmode "light" --unlock 7a67c39db201fbba9e9e0e...
  • Avoid entering your password in the Geth’s Javascript interactive console, and if you do, erase the $HOME/.ethereum/history file. If you execute personal.unlockAccount(eth.accounts[0], "myethsecret", 5) you will be able to see your password printed in the .history file mentioned above. By default the directory in which your .history file is located is only readable by your own system user. But if your system user account is compromised, your password will be visible in your history file.
  • Consider using a wallet to interact with the Ethereum blockchain. For e.g. using Metamask you can securely manage your account, use your account to authenticate to websites and send transactions.

Conclusion

In this post we tried to undertand why Geth disallows unlocking accounts when the HTTP or Websockets interface is enabled, potential risks in that scenario and best practices when working with accounts.

Thats all for now. Stay tuned for more! Please share your thoughts in the comments below and 👏for this post if you found it helpful.

--

--