# The preimage DB (i.e., NameWrapper.names) can be maliciously manipulated/corrupted

NameWrapper.setSubnodeOwner checks ens.owner(node)==address(this) instead of names[node], letting an attacker pre-set registry ownership to corrupt the preimage DB.

- Payout: Contest reward
- Severity: medium
- Program: ENS
- Credited: PwnedNoMore
- Disclosed: 2022-12-13
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-07-ens-findings/issues/197
- Library page: https://bugbountylibrary.com/r/c4%3A2022-07-ens%3AM-11
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** NameWrapper.sol setSubnodeOwner/setSubnodeRecord preimage DB
**Root cause:** Wrapped-state check uses ens.owner(node) != address(this) rather than checking NameWrapper.names[node], so a node can be owned by the wrapper in the registry without a recorded preimage.
**Steps:**
1. Register `base.eth`; create `sub1.base.eth` with short expiry
2. Wait for expiry and unwrap `sub1.base.eth`
3. Call `ens.setSubnodeOwner` to set owner of `sub2.sub1.base.eth` to NameWrapper address
4. Re-wrap `sub1.base.eth`
5. Call `nameWrapper.setSubnodeOwner` for `sub2.sub1.base.eth` — `names[labelhash]` stays empty
6. Call `nameWrapper.setSubnodeOwner` for `eth.sub2.sub1.base.eth` — `names[labelhash]` becomes `\x03eth`
**How found:** Code reading of setSubnodeOwner revealed the wrapped-state check relies on ens.owner(node) rather than the preimage DB, prompting the hypothesis that registry ownership could be set externally to bypass it.
**Exploitation:** Attacker manipulates registry ownership so the wrapper's wrapped-check passes without a stored preimage, then wraps nested labels to write malformed/empty preimages into NameWrapper.names.
**Insight:** When a contract uses an external registry's ownership as a proxy for its own internal state, look for ways to set that external ownership directly to desync the two.
