Skip to main content
Sigvex

Private Data Exposure Remediation

How to stop treating the private keyword as confidentiality: never store secrets on-chain in plaintext.

Private Data Exposure Remediation

Overview

Related Detector: Private Data Exposure

Solidity’s private and internal control contract-to-contract access, not confidentiality. Every storage slot is readable by anyone via eth_getStorageAt, and every transaction input is public. Storing a password, secret key, or hidden parameter in a private variable exposes it. The remediation is to never place a secret on-chain in the clear — keep it off-chain and commit only to a binding hash.

Before (Vulnerable)

contract Game {
    bytes32 private secret;   // fully readable via eth_getStorageAt
    function setSecret(bytes32 s) external onlyOwner { secret = s; }
}

After (Fixed — commit-reveal, no plaintext secret on-chain)

contract Game {
    bytes32 public commitment;   // hash only; the preimage stays off-chain

    function commit(bytes32 c) external onlyOwner { commitment = c; }

    function reveal(bytes32 secret, bytes32 salt) external {
        require(keccak256(abi.encodePacked(secret, salt)) == commitment, "Bad reveal");
        // act on the now-public secret
    }
}

Store only a keccak256(secret, salt) commitment; reveal later when the value is meant to become public. For data that must stay confidential indefinitely, keep it entirely off-chain.

Common Mistakes

  • Believing private hides a value from users; it only blocks other contracts from reading it directly.
  • Committing to keccak256(secret) without a salt, allowing a brute-force/rainbow-table recovery of low-entropy secrets.
  • Passing the secret as a plaintext transaction argument during “reveal” before it should be public — the mempool sees it.

References