Web3Exploit logoWeb3Exploit
← Back to Attack Patterns
Attack pattern

Access Control

A privileged action is reachable by the wrong caller because a check is missing, wrong, or built on a broken assumption.

Definition

Access-control vulnerabilities arise when a sensitive function (minting, upgrading, withdrawing, configuring) can be invoked by an actor who should not have permission — due to a missing modifier, a flawed role check, an unprotected initializer, or a guard whose assumption no longer holds.

How it works

  1. A function that mutates funds or configuration lacks a correct authorization check.
  2. An attacker calls it directly, or satisfies a guard that was never truly restrictive.
  3. The privileged action executes under attacker control (mint, upgrade, drain, or re-parameterize).

Vulnerable vs. fixed

Vulnerable: unprotected privileged functionsolidity
// Missing access control — anyone can point the proxy at new logic.
function setImplementation(address impl) external {
    implementation = impl;
}
Fixed: explicit, tested authorizationsolidity
function setImplementation(address impl) external onlyOwner {
    require(impl.code.length > 0, "not a contract");
    implementation = impl;
    emit ImplementationUpdated(impl);
}

Detection steps

  1. Identify the sensitive value or permission the pattern can influence.
  2. Trace every path that can update or consume that value, including callbacks, routers, and privileged helpers.
  3. Reproduce the worst-case attacker flow with adversarial ordering, manipulated inputs, and maximum feasible capital.

Common signals

  • Security depends on an assumption that is not enforced by code.
  • A critical value is consumed immediately after an attacker-controlled interaction.
  • A privileged call path crosses multiple contracts without one clear authorization boundary.

False positives

  • The risky-looking operation is read-only and cannot affect settlement or authorization.
  • The value is bounded by independent checks before it moves assets.
  • All privileged entry points share the same tested guard and monitoring path.

Review questions

  • Which invariant would fail if this input or caller were attacker-controlled?
  • Can the attacker compose setup, trigger, settlement, and cleanup atomically?
  • What independent check stops the exploit if the first guard is wrong?

Defensive checklist

  • Gate every state-mutating privileged function with an explicit, tested check.
  • Protect initializers against re-initialization and front-running.
  • Prefer role-based access control with least privilege over ad-hoc address checks.
  • Re-validate guards whose safety depends on protocol- or chain-level assumptions.