Skip to content

N-07: Owner Commitments Are Not Truly Distinct Over Multiple Contracts #812

Description

@andrew-fleming

N-08 Owner Commitments Are Not Truly Distinct Over Multiple Contracts

Severity: Note

Source: Midnight Foundation #2 — OpenZeppelin Compact Contracts Audit, Release 0.3.0-alpha.1 (2026-08-18)


Ownership in ZOwnablePK is represented by a public commitment, returned by owner() and derived by _computeOwnerCommitment as a persistentHash over the owner identifier, the _instanceSalt, a counter and a fixed domain tag. Of those four inputs only the salt varies between deployments, the tag being a constant, so the salt alone provides the per-instance namespace the module documents it as providing.

initialize rejects a zero owner identifier but persists the salt without validating it. Two deployments that share an owner identifier and are both initialized with the type default therefore publish identical commitments at the same counter value, and an observer can correlate administrative identity across those contracts by comparing a public getter. Authorization behavior is unchanged, since the commitment still requires a preimage to satisfy the owner check, so the consequence is the loss of the unlinkability the salt exists to provide.

Consider rejecting a salt equal to the type default in initialize, matching the check already applied to the owner identifier on the line above. Consider also folding a contract-unique value such as kernel.self() into the commitment, so that deployments remain namespaced even where a consumer supplies a poor salt.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Backlog
    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions