The book Mastering Ethereum pointed out that it is not safe to use tx.origin in smart contracts. I want to know what is the reason for insecurity?
Primarily to protect against phishing contracts.
tx.origin is the original user that initiated the transaction.
So if contract has some method like this (in Vyper):
def burnBalance(): assert tx.origin == owner, "You are not the owner" balance[tx.origin] = 0
Then another smart contract can "phish" you with a proxy function - If you accidentally interact with this evil contract then you will lose your funds:
# The attacking contract calling the original contract OriginalContract(originalContractAddress).burnBalance()
burnBalance was instead using msg.sender then this attack will fail:
# This is the correct way of checking permissions def burnBalance(): assert msg.sender == owner, "You are not the owner" balance[msg.sender] = 0
msg.sender is the intermediate caller; In this case the phishing contract is the
Sidenote: There is actually some discussion in the ethereum community on removing tx.origin all together. Personally I disagree with this as it has some niche use cases. One of which is checking if the caller who is interacting with the smart contract is another smart contract or a normal user. e.g.
assert tx.origin == msg.sender, "Only users can interact with this contract"