feat(rules): [RULE] Rule B004: Detect Zero-Address Comparisons in Recovered Signatures (#826) - #950
Merged
mijinummi merged 1 commit intoAug 25, 2026
Conversation
…overed Signatures (MDTechLabs#826)
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[RULE] Rule B004: Detect Zero-Address Comparisons in Recovered Signatures (#826)
📌 Overview & Motivation
Closes #826
When Ethereum's native
ecrecoverprecompile/built-in function processes malformed or invalid signature parameters (such as invalidv,r, orsvalues outside the curve order), it fails silently and returnsaddress(0)instead of reverting.If a smart contract compares this recovered address directly against:
address(0)),the comparison evaluates to
true, resulting in a critical signature authorization bypass.This PR introduces static analysis rule B004 (
ecrecover-zero-address) to inspect Solidity ASTs, detect unguardedecrecoverinvocations, and enforce explicitaddress(0)validations or recommend OpenZeppelin'sECDSA.recover.🔍 Vulnerability Mechanism & Real-World Impact
🛠️ Implementation Details
1. AST Traversal & Detection Engine (
rules/b004_ecrecover_zero.rs)solang-parserto parse Solidity source units, inspecting functions, constructors, and modifiers.Statement::VariableDefinitionandExpression::Assignwhereecrecoveris invoked.ecrecover(...)calls.!= address(0),!(ecrecover == address(0))).Statement::Assemblyblocks for directecrecoveropcode calls orstaticcall(gas(), 1, ...)(precompile 1) lackingiszero/ non-zero validations.require(signer != address(0), ...)/require(address(0) != signer, ...)assert(signer != address(0))if (signer == address(0)) revert CustomError();require(signer != address(0) && signer == expected);ECDSA.recover(hash, signature)orhash.recover(sig)(automatically recognized as safe and excluded from flags).2. Actionable Remediation Guidance
Emits structured diagnostic findings with file, line number,
Severity::High, and clear remediation instructions pointing to OpenZeppelin's battle-testedECDSAlibrary or explicit assertions.🧪 Test Matrix & Fixtures (
test/fixtures/b004_samples.sol)A comprehensive test suite with 6 dedicated test cases and fixture evaluations:
verifySignatureUncheckedexecuteAsAdminrequire(ecrecover(...) == admin)recoverSignerreturn ecrecover(...)without assertionexecuteIfValidatorif (recovered == expected)without zero checkrecoverAssemblyiszerocheckverifyGuardedRequirerequire(signer != address(0))verifyCombinedRequirerequire(signer != address(0) && ...)verifyGuardedRevertif (signer == address(0)) revertverifyInlineGuardedrequire(ecrecover != 0 && ...)verifyECDSAECDSA.recover(hash, v, r, s)verifyECDSAMemberhash.recover(signature)setAdmin📂 File Changes Summary
rules/b004_ecrecover_zero.rstest/fixtures/b004_samples.solrules/mod.rsb004_ecrecover_zeromodulerules/src/lib.rsrules/Cargo.toml🚀 Verification Results
📋 Checklist
rules/b004_ecrecover_zero.rsecrecovercall expressions lacking non-zero address assertionsrequire != address(0),if == address(0) revert, OpenZeppelinECDSA.recover)test/fixtures/b004_samples.solcargo test)