example-fork-detection
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on…
Detect ERC-1271 contract-signature bugs — magic-value handling, signature validation edge cases, smart-wallet interactions (Safe, Argent), replay-via-signature-update. Activate on `isValidSignature`, ERC1271 imports, smart-wallet integration, signed orders that may originate
Claude Code
$ npx -y skills add omermaksutii/RugProof --skill erc1271-contract-signatures --agent claude-code
Codex
$ npx skills add omermaksutii/RugProof --skill erc1271-contract-signatures -a codex -y
Cursor
$ npx skills add omermaksutii/RugProof --skill erc1271-contract-signatures -a cursor -y
Gemini CLI
$ npx skills add omermaksutii/RugProof --skill erc1271-contract-signatures -a gemini-cli -y
GitHub Copilot
$ npx skills add omermaksutii/RugProof --skill erc1271-contract-signatures -a github-copilot -y
OpenCode
$ npx skills add omermaksutii/RugProof --skill erc1271-contract-signatures -a opencode -y
Windsurf
$ npx skills add omermaksutii/RugProof --skill erc1271-contract-signatures -a windsurf -y
name: erc1271-contract-signatures description: Detect ERC-1271 contract-signature bugs — magic-value handling, signature validation edge cases, smart-wallet interactions (Safe, Argent), replay-via-signature-update. Activate on `isValidSignature`, ERC1271 imports, smart-wallet integration, signed orders that may originate from contracts.
ERC-1271 lets contract accounts (smart wallets, multisigs) sign messages. Verification call:
IERC1271(signer).isValidSignature(hash, sig) returns (bytes4 magicValue); // magicValue must equal 0x1626ba7e
Without ERC-1271, smart-wallet users can't sign anything (no private key).
require(ecrecover(hash, v, r, s) == signer, "bad sig"); // ← signer is a smart wallet, ecrecover returns address(0), check fails legitimately
The bug: contract owners can't sign at all. Add an ERC-1271 fallback:
if (signer.code.length > 0) {
require(IERC1271(signer).isValidSignature(hash, abi.encodePacked(r, s, v)) == 0x1626ba7e);
} else {
require(ecrecover(hash, v, r, s) == signer);
}require(IERC1271(signer).isValidSignature(hash, sig) == 0x1626ba7c); // ← typo: should be 0x1626ba7e
Some old impls return `0x20c13b0b` (the legacy bytes-based variant). Spec is hash-based `0x1626ba7e`. Mixing → reject valid sigs.
A Safe's `isValidSignature` checks owner approvals. If signature is approved via on-chain `approveHash` then consumed, can it be re-approved later? Replay risk.
If owner rotates, previously-validated signatures may now be valid by different signer logic. Depends on wallet impl.
ERC-1271 returns `bytes4`. Naive callers using `staticcall` + manual returndata parsing can mis-decode.
Smart wallet impl can spend unbounded gas in `isValidSignature` → relayer griefing.
Permit2 must handle contract signers. Apps that wrap Permit2 must too.
| Pattern | Severity | |---|---| | App rejects smart-wallet users entirely (no 1271 fallback) | **High** *(usability — but also gives an exploitable bypass if mixed)* | | Wrong magic value | **High** | | Pre-EIP magic value not handled | **High** | | Replay via approve-on-chain on Safe | **High** | | Returning data length not validated | **High** | | Unbounded gas in isValidSignature | **Medium** |
Rugproof your code before someone else does. 🌐 Live site: omermaksutii.github.io/RugProof 📦 Latest: v1.0.0 — 45 commands · 23 agents · 45 skills · 13 MCP servers · tested, offline-first, with rule packs, a benchmark, non-EVM coverage, and post-deploy
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on…
Detect unsafe assumptions about Solady's gas-optimized ERC20/ERC2612 permit and DN404 metadata. Solady's ERC20 uses custom…
Detect front-runnable ownership initialization in Solady Ownable / OwnableRoles. Solady's `_initializeOwner` is a guarded…
Detect Solady SafeTransferLib calls that assume the token has code. SafeTransferLib.safeTransfer/safeTransferFrom/safeApprove…
Detect Uniswap V4 hooks that fail to settle currency deltas with the PoolManager. Every credit/debit a hook creates…
Detect Uniswap V4 hooks whose address-encoded permission flags don't match the callbacks the hook actually implements. In V4 the…
Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…
Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys)…
Clean and finalize authorized natural-language text intended for readers by auditing suspicious invisible Unicode and rewriting…