Skip to content

Public Mappings

id: LS13M
title: Public Mappings
baseSeverity: M
category: data-leakage
language: solidity
blockchain: [ethereum]
impact: Unauthorized access to sensitive information via auto-generated getter
status: draft
complexity: low
attack_vector: external
mitigation_difficulty: easy
versions: [">=0.4.0", "<=0.8.25"]
cwe: CWE-200
swc: SWC-136

πŸ“ Description

  • In Solidity, declaring a mapping as public automatically generates a getter function for it.
  • However, when the mapping contains nested types (such as structs, arrays, or other mappings), the auto-generated getter allows external users to retrieve internal state values on-demand, exposing potentially sensitive data.
  • While this is not a vulnerability in all contexts, it becomes critical when:
  • The nested data includes sensitive business logic (e.g., votes, KYC status, secret salts).
  • The mapping is assumed to be β€œinternal-only” due to its type or naming.
  • Access control checks are bypassed unintentionally due to auto-exposure.

🚨 Vulnerable Code

pragma solidity ^0.8.0;

contract VoteTracker {
    struct Vote {
        bool hasVoted;
        uint8 choice;
    }

    mapping(address => Vote) public votes; // ❌ Public mapping exposes Vote struct
}

πŸ§ͺ Exploit Scenario

  1. A contract implements a voting system with Vote structs mapped per user.
  2. The mapping is declared public to enable internal read access (e.g., votes[msg.sender]).
  3. An attacker or curious user queries votes(victimAddress) directly via the generated getter.
  4. Sensitive data like vote choices or flags are publicly revealed.

Assumptions:

  • Developers are unaware of the full implications of public on mappings.
  • Sensitive data is nested under mappings assumed to be internally scoped.
  • No external access guard is applied to the getter.

βœ… Fixed Code

pragma solidity ^0.8.0;

contract SecureVoteTracker {
    struct Vote {
        bool hasVoted;
        uint8 choice;
    }

    mapping(address => Vote) internal votes; // βœ… Internal prevents external access

    function hasVoted(address user) external view returns (bool) {
        return votes[user].hasVoted;
    }
}

🧭 Contextual Severity

- context: "Default"
  severity: M
  reasoning: "Can lead to sensitive data exposure and governance manipulation in common use cases."
- context: "Public DeFi Protocol with token-based voting"
  severity: H
  reasoning: "Vote buying, stake-based manipulation, or airdrop sybil attacks possible."
- context: "Private/internal app with low user count"
  severity: L
  reasoning: "Limited damage; user addresses likely known or non-sensitive."

πŸ›‘οΈ Prevention

Primary Defenses

  • Do not mark nested mappings or mappings of structs as public if data confidentiality is expected.
  • Use custom getter functions with access control as needed.

Additional Safeguards

  • Restrict contract functions to return redacted or masked data.
  • Design mappings with visibility expectations explicitly documented.
  • Consider zero-knowledge or hash-based storage for privacy-critical logic.

Detection Methods

  • Search for public mapping(address => Struct) or similar patterns.
  • Check if nested values expose user privacy, choices, or business-critical flags.
  • Tools: Slither (public-mapping-struct rule), manual audit

πŸ•°οΈ Historical Exploits

  • Name: Confidential Airdrop Whitelist Exposure
  • Date: 2021
  • Loss: No funds lost, but targeted sybil attacks observed
  • Post-mortem: Link to post-mortem

πŸ“š Further Reading


βœ… Vulnerability Report

id: LS13M
title: Public Mappings 
severity: M
score:
impact: 3         
exploitability: 3 
reachability: 5   
complexity: 2     
detectability: 3  
finalScore: 3.25

πŸ“„ Justifications & Analysis

  • Impact: Reveals sensitive or strategic information; affects fairness or integrity.
  • Exploitability: Simple external call retrieves supposedly private data.
  • Reachability: Fully exposed via public getter generated by Solidity.
  • Complexity: Low-complexity coding mistake; misunderstood visibility semantics.
  • Detectability: Easy to overlook unless audit explicitly checks visibility of mappings.