Default Visibility
Detects functions and state variables with implicit visibility that may unintentionally be public.
Default Visibility
Overview
The default visibility detector identifies functions and state variables that do not explicitly declare their visibility (public, external, internal, or private). In Solidity versions before 0.5.0, functions defaulted to public visibility. A developer who omits the visibility keyword may not realize the function is publicly callable, creating an unintended entry point.
Why This Is an Issue
A function intended to be internal that defaults to public can be called by anyone, potentially bypassing access control. The Parity wallet hack ($30M) exploited an unintentionally public initialization function. While Solidity 0.5.0+ requires explicit visibility, many deployed contracts and contracts targeting older versions still have this issue.
How to Resolve
// Before: Missing visibility (defaults to public in <0.5.0)
function initialize(address owner) {
_owner = owner;
}
// After: Explicit visibility
function initialize(address owner) internal {
_owner = owner;
}
Detection Methodology
- Compiler version detection: Determines the Solidity version from bytecode metadata.
- Function dispatch analysis: Identifies all externally-callable function selectors in the dispatcher.
- Cross-reference: For contracts with source, checks whether visibility keywords are present. For bytecode-only analysis, flags functions that appear in the public dispatch table but have patterns suggesting internal intent (e.g., underscore prefix, no parameter validation).
Limitations
False positives: Functions intentionally public without explicit keyword in older Solidity. False negatives: In Solidity 0.5.0+, the compiler enforces explicit visibility, making this detector primarily relevant for legacy contracts.
Related Detectors
- Access Control — detects missing authorization on critical functions