SWC·SWC-105·critical

Unprotected access / privileged functions

A function that moves money or changes ownership has no modifier restricting who can call it.

What it is

Solidity functions are externally callable by default when marked public or external. A privileged operation — mint, pause, withdraw, upgrade, setFee, transferOwnership — that ships without an access-control modifier is callable by anyone on the network.

Why it matters

Whatever the function does, anyone can do. An unguarded mint is a public faucet for your token; an unguarded withdraw empties the contract. Deployed contracts are scanned continuously, so these are found within minutes, not months.

The vulnerable pattern

No modifier — any address can mint.

function mint(address to, uint256 amount) external {
    _mint(to, amount);
}

The fix, in code

Restricted, capped, and observable.

function mint(address to, uint256 amount) external onlyOwner {
    require(totalSupply() + amount <= MAX_SUPPLY, "cap exceeded");
    _mint(to, amount);
    emit Minted(to, amount);
}

How to fix it

  • List every state-changing function and name who should be able to call it. Anything without an answer is a finding.
  • Use a maintained implementation — OpenZeppelin Ownable or AccessControl — rather than a hand-rolled owner check.
  • Put privileged roles behind a multisig, and a timelock where the action is irreversible.
  • Emit an event on every privileged action so monitoring can see it happen.

How it is detected

Every audit on EVM Smart Audit checks for SWC-105 and reports it as passed or flagged in the standards coverage grid — so the report tells you it was checked even when nothing was found. See the detector suite for what else runs alongside it, or the full database for the other 21 checks.

Related weaknesses

Check your contract for unprotected access / privileged functions

The engine runs this check and 21 others on every audit, and shows what passed as well as what failed.

Start your auditSee pricing