Safeguard
Security Guides•

tx.origin vs msg.sender: which to use for authorization

Never use tx.origin to check who is allowed to act in a Solidity contract. Here is why msg.sender is the safe choice and how the phishing attack works.

Safeguard Security Team
3 min read

Use msg.sender for authorization and never tx.origin. The Solidity documentation says so directly. The reason is that tx.origin is the account that started the whole transaction, so a malicious contract that the owner is tricked into calling can pass the owner's address along and act as them.

What each value means

msg.sender is the address that called the current function. It changes as calls pass from contract to contract. tx.origin is the externally owned account that signed the original transaction. It stays the same through the whole chain of calls.

How the attack works

Suppose a wallet contract lets its owner withdraw, and it checks that tx.origin equals the owner. An attacker deploys a contract with an innocent looking function. They persuade the owner to call it, perhaps through a fake airdrop or a game.

Inside that function the attacker's contract calls the wallet. The wallet sees tx.origin equal to the owner and approves the withdrawal. The owner never meant to authorize anything, but the check passed.

The Solidity documentation describes this scenario: a malicious intermediary contract can supply the owner's address as tx.origin and drain the wallet.

The fix

require(msg.sender == owner);

With msg.sender, the wallet sees the attacker's contract as the caller, not the owner, and the check fails.

Is there ever a reason to use tx.origin

Rarely, and almost never for permission checks. Some people use it to block contracts from calling a function at all, but that is a fragile design choice, and it can break legitimate smart wallets. If you think you need it, write down the threat model first and have someone else review it.

How to catch it

  • Search your code for tx.origin during review.
  • Run a static analyzer. The Slither project lists tx.origin use among the issues its detectors look for.
  • Add a test where a hostile intermediary contract calls your function as the owner would.

Quick check

Is tx.origin ever the same as msg.sender?

Yes, when a person calls your contract directly. They differ as soon as another contract sits in between, which is exactly the case an attacker creates.

Does a multisig fix this?

Only if the check inside your contract uses msg.sender. A bad check is bad whoever owns the account.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.