iktok90-design/ai-smart-contract-auditor/signature-malleability
Claude Code and agent skill by iktok90-design/ai-smart-contract-auditor
- community
Checking that the SKILL.md file is still in the repository.
Detect ECDSA signature malleability and ecrecover pitfalls — missing low-s (EIP-2) enforcement, unconstrained v, unchecked address(0) from ecrecover, replay across chainId/contract from a missing EIP-712 domain separator, EIP-2098 compact-signature confusion, and signature reuse. Activate whenever code calls ecrecover directly, parses (r,s,v) from bytes, or verifies signed messages without OpenZeppelin ECDSA.
Install
npx vskill@latest install iktok90-design/ai-smart-contract-auditor/signature-malleabilitySKILL.md
Signature malleability detection
When this applies
Trigger on any of:
- Direct
ecrecover(hash, v, r, s)calls (not via OpenZeppelinECDSA.recover) - Manual
(r, s, v)decoding from abytessignature with assembly - Permit / meta-tx / order-book / claim flows that verify a signed digest
- Signatures used as nonces or dedup keys (e.g.
usedSig[sig] = true) - EIP-712 typed-data verification, or its absence where one is needed
Detection patterns
Missing low-s enforcement / malleable sig (HIGH if sig is a key)
Signal: for any valid (r,s,v) the "flipped" signature (r, n - s, v ^ 1) recovers the same signer (the classic Bitcoin/Ethereum transaction-malleability class). If the signature itself is the replay key, an attacker submits the twin and bypasses dedup. Enforce s <= secp256k1n/2 (EIP-2).
Unchecked ecrecover returning address(0) (HIGH)
Signal: malformed inputs make ecrecover return address(0). Any code path where the compared-against value can be address(0) (uninitialized mapping slot, default) authenticates an attacker with garbage. Always require(signer != address(0)).
Unconstrained v (MEDIUM)
Accepting arbitrary v (not 27/28) or trusting a caller-supplied v for EIP-2098 compact sigs, mixing the 64-byte and 65-byte formats. EIP-2098 packs yParity into the high bit of s; decoding it as a raw 65-byte sig corrupts recovery.
Cross-domain / cross-chain replay (HIGH)
Signal: no EIP-712 domain separator binding chainId and verifyingContract. A signature is replayable on another chain (post-fork) or a sibling deployment. Build the digest with _hashTypedDataV4 (\x19\x01 + domainSeparator + structHash) and recompute the domain separator if block.chainid changes.
Signature reuse / no nonce (HIGH)
Same digest accepted twice because there's no per-signer nonce or no marking of consumed digests — meta-tx and claim flows drain repeatedly.
Severity rubric
| Pattern | Severity | Notes | |
|---|---|---|---|
| Malleable sig used as replay/dedup key | High | Twin sig bypasses guard | |
| ecrecover==address(0) authenticates attacker | High | Auth bypass | |
| Missing EIP-712 domain → cross-chain replay | High | Signature reuse across deployments | |
| No nonce → straight replay | High | Repeated execution | |
| Unconstrained v / EIP-2098 confusion | Medium | Format-dependent | |
| Low-s missing but sig never used as a key | Low | Defense-in-depth |
Remediation patterns
- Use OpenZeppelin `ECDSA.recover` — it enforces
s <= secp256k1n/2, rejects badv, and reverts onaddress(0)(it also handles EIP-2098). - Bind digests with EIP-712 (
EIP712base +_hashTypedDataV4), includingchainIdandverifyingContract; recompute the domain separator on chainid change. - Use per-signer nonces (incrementing) rather than signature-bytes dedup; consume by
(signer, nonce)not(r,s,v). - Explicit `require(signer != address(0))` even when using libraries, for any hand-rolled path.
- Prefer `SignatureChecker` when signers may be ERC-1271 contract wallets.
False-positive notes
- Code already routing through OpenZeppelin
ECDSA/SignatureCheckerwith EIP-712 and nonces is safe — don't re-flag the underlyingecrecover. - A sig verified against a non-zero, always-set signer where the digest is never reused is malleability-tolerant; note, don't escalate.
Related
- [[signature-replay]] — nonce/chainId replay is the sibling concern
- [[erc1271-contract-signatures]] — smart-wallet signers need
isValidSignature - [[permit2-patterns]] — Permit2 / EIP-2612 digests and nonces
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/signature-malleability/SKILL.md
Popularity
- Repository stars
- 37
- Repository forks
- 5
- 7-day trend score
- 18
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/iktok90-design/ai-smart-contract-auditor/signature-malleability)