# Multiple accounts can have the same identity

AddressRegistry.register() lets multiple accounts register the same CID NFT, so two wallets share one on-chain identity and its traits.

- Payout: Contest reward
- Severity: medium
- Program: Canto Identity Protocol
- Credited: joestakey
- Disclosed: 2023-04-06
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-01-canto-identity-findings/issues/177
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-canto-identity%3AM-02
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** AddressRegistry.register() identity registry contract
**Root cause:** register() only checks current NFT ownership and writes cidNFTs[msg.sender] without tracking which account owns a given cidNFTID, so a transferred NFT can be re-registered by the new owner while the old owner's mapping persists.
**Steps:**
1. Alice mints CID NFT id 1 and calls `addressRegistry.register(1)`
2. Alice transfers NFT 1 to Bob via `cidNFT.transferFrom(Alice, Bob, 1)`
3. Bob calls `addressRegistry.register(1)`
4. `addressRegistry.getCID(Alice) == addressRegistry.getCID(Bob) == 1`
**How found:** Code reading of register(): noticed the function only validates ownership at registration time and never invalidates prior registrations on transfer, so the same cidNFTID can map to multiple addresses.
**Exploitation:** After transfer, the previous owner's registration is never cleared; the new owner registers the same ID, so both accounts resolve to one identity. The new owner pays for subprotocol trait NFTs via CidNFT.add(), and the stale-linked account gains those traits for free and can front-run trait-gated rewards.
**Insight:** When a registry maps address->ID, check whether the reverse (ID->address) is tracked; any transferable token used as an identity key needs its old registration cleared on transfer, otherwise stale mappings grant shared identity and free traits.
