# updateProjectHash does not check project address

updateProjectHash omits the project-address check present in other functions, letting a signature from one project be replayed on another with the same parties and nonce.

- Payout: Contest reward
- Severity: medium
- Program: Rigor Protocol
- Credited: MEP
- Disclosed: 2022-09-12
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-08-rigor-findings/issues/347
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-rigor%3AM-12
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:signature-replay

**Target:** Project.sol smart contract, updateProjectHash function
**Root cause:** updateProjectHash verifies a builder/contractor signature over _data but _data lacks the project address, unlike other external functions that enforce `_projectAddress == address(this)`.
**Steps:**
1. Identify two projects sharing the same builder and/or contractor.
2. Obtain a valid `_data`/`_signature` pair from project A's updateProjectHash.
3. Wait until project B's `_nonce` matches the nonce in the captured `_data`.
4. Call `updateProjectHash` on project B with the replayed `_data` and `_signature`; the missing `require(_projectAddress == address(this))` allows it to pass.
5. Task hash on project B is overwritten.
**How found:** Noticed that every other external function in Project.sol includes the project-address check in signed `_data`, but updateProjectHash does not, implying cross-project signature reuse.
**Exploitation:** Replay a previously signed updateProjectHash payload on a different project instance once its nonce aligns, overwriting a task hash without authorization.
**Insight:** When auditing signature-verification functions, diff the signed payload fields across all functions in the contract; any function missing a domain-separator field (address, chainId) that siblings include is a replay candidate.
