Access Control

Authorization

Missing or incorrect access control is one of the most common smart contract vulnerabilities. Functions meant to be restricted can be called by anyone.

Common Access Control Issues

access-control.sol
solidity
// VULNERABLE: Missing access control
contract Vulnerable {
    address public owner;
    
    constructor() {
        owner = msg.sender;
    }
    
    // Anyone can call this!
    function setOwner(address newOwner) public {
        owner = newOwner;
    }
    
    // Missing modifier
    function withdrawAll() public {
        payable(owner).transfer(address(this).balance);
    }
}

// SECURE: Proper access control
contract Secure {
    address public owner;
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    function setOwner(address newOwner) public onlyOwner {
        owner = newOwner;
    }
    
    function withdrawAll() public onlyOwner {
        payable(owner).transfer(address(this).balance);
    }
}

tx.origin Phishing

txorigin-attack.sol
solidity
// VULNERABLE: Using tx.origin for auth
contract TxOriginVictim {
    address public owner;
    
    function withdrawAll() public {
        require(tx.origin == owner);  // BAD!
        payable(msg.sender).transfer(address(this).balance);
    }
}

// ATTACK: Trick owner into calling attacker contract
contract TxOriginAttacker {
    TxOriginVictim victim;
    address attacker;
    
    constructor(address _victim) {
        victim = TxOriginVictim(_victim);
        attacker = msg.sender;
    }
    
    // Owner calls this function (e.g., via phishing)
    // tx.origin is still the owner!
    function attack() public {
        victim.withdrawAll();  // Passes tx.origin check
    }
}

Always Use msg.sender

Never use tx.origin for authentication. It can be manipulated through intermediate contract calls.