maxSigners can be bypassed
maxSigners is specified when creating an HSG and is left constant. It is enforced in two ways -targetThreshold may never be set above it, and new signers cannot register to the HSG when the signer count reached maxSigners. Below is the implementation code in HatsSignerGate.\\n```\\n        function claimSigner() public virtual {\\n             if (signerCount == maxSigners) {\\n                revert MaxSignersReached();\\n        }\\n        if (safe.isOwner(msg.sender)) {\\n                revert SignerAlreadyClaimed(msg.sender);\\n            }\\n        if (!isValidSigner(msg.sender)) {\\n             revert NotSignerHatWearer(msg.sender);\\n         }\\n         _grantSigner(msg.sender);\\n           }\\n```\\n\\nAn issue that arises is that this doesn't actually limit the number of registered signers. Indeed, signerCount is a variable that can fluctuate when wearers lose eligibility or a hat is inactive. At this point, `reconcileSignerCount()` can be called to update the signerCount to the current valid wearer count. A simple attack which achieves unlimited claims is as follows:\\nAssume maxSigners = 10\\n10 signers claim their spot, so signerCount is maxed out\\nA signer misbehaves, loses eligibility and the hat.\\nreconcile() is called, so signerCount is updated to 9\\nA new signer claims, making signerCount = 10\\nThe malicious signer behaves nicely and regains the hat.\\nreconcile() is called again, making signerCount = 11\\nAt this point, any eligible hat wearer can claim their hat, easily overrunning the maxSigners restriction.
The root cause is that users which registered but lose their hat are still stored in the safe's owners array, meaning they can always get re-introduced and bump the signerCount. Instead of checking the signerCount, a better idea would be to compare with the list of owners saved on the safe. If there are owners that are no longer holders, `removeSigner()` can be called to vacate space for new signers.
```\\n        function claimSigner() public virtual {\\n             if (signerCount == maxSigners) {\\n                revert MaxSignersReached();\\n        }\\n        if (safe.isOwner(msg.sender)) {\\n                revert SignerAlreadyClaimed(msg.sender);\\n            }\\n        if (!isValidSigner(msg.sender)) {\\n             revert NotSignerHatWearer(msg.sender);\\n         }\\n         _grantSigner(msg.sender);\\n           }\\n```\\n