
Consider a scenario where (1) the wallet is behind the checkpointer and (2) a chained signature is used; however, bit 6 (0x40 - the checkpointer usage flag) is zero. As a result, when BaseSig.recover is called the below if-block on BaseSig.sol:88-106 will be skipped:

We can see that this will leave the following variables unset (zero-valued):
- _checkpointer
- snapshot.checkpoint
- snapshot.imageHash
We then enter recoverChained with the above unset variables passed in:

Let’s assume the signature chain contains one signature. Therefore, in the first loop iteration above nrindex == _signature.length and address checkpointer is set to _checkpointer = address(0).
We then enter recover again - this time with _ignoreCheckpointer == true and _checkpointer == address(0). Bit 6 (0x40) can be set to 1 for the signature inside the chain, and so we enter the if block shown earlier but ignore the checkpointer:

To make signature validation succeed, it is easy enough to provide the necessary checkpointer, checkpoint and threshold. Assuming the non-chained signature is valid, with respect to the wallet configuration, the recovered imageHash will be valid. The final validation of the non-chained signature (BaseSig.sol:138-140) will succeed because snapshot.imageHash == bytes32(0) as the checkpointer has been ignored:

Finally, we end up back in recoverChained (BaseSig.sol:179-193) and all the validations will pass (comments added below for explanation):

After all this, the signature recovery doesn’t revert and returns an image hash; which is valid for the wallet’s current configuration. The checkpointer has been ignored completely.
Alpha: check for inconsistent states in the flags used, what happens if a flag is off but the functionality is still used?
Conclusion
This finding would earn you $19609, requiring an understanding of the flags used and the wallet structure, mixed with the attack vector of trying to do actions on behalf of the wallet skipping the regular checks.