@elytrasec/engine 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +23 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3477,8 +3477,11 @@ var solidityRules2 = [
|
|
|
3477
3477
|
title: "Chainlink latestRoundData without staleness check",
|
|
3478
3478
|
description: "Using latestRoundData() without checking updatedAt for staleness can return outdated prices.",
|
|
3479
3479
|
suggestion: "Check that `updatedAt` is recent: `require(block.timestamp - updatedAt < STALENESS_THRESHOLD)`.",
|
|
3480
|
-
pattern:
|
|
3481
|
-
multilinePattern
|
|
3480
|
+
// Removed single-line pattern: it fired on EVERY interface declaration of latestRoundData().
|
|
3481
|
+
// Only the multilinePattern below should fire — it scopes to actual usage with no staleness check.
|
|
3482
|
+
// Match real usage (destructured assignment), suppress when staleness/sequencer/heartbeat
|
|
3483
|
+
// checks are visible in the next ~1500 chars. Skip pure interface declarations.
|
|
3484
|
+
multilinePattern: /\(\s*[^)]*\)\s*=\s*[^;]*\.latestRoundData\s*\(\s*\)(?![\s\S]{0,1500}?(?:updatedAt|staleness|MAX_DELAY|STALENESS|grace|GRACE|timestamp\s*-\s*updatedAt|block\.timestamp\s*-\s*\w+|sequencer|isSequencerUp|MAX_HEARTBEAT|HEARTBEAT|maxAge))/,
|
|
3482
3485
|
severity: "high",
|
|
3483
3486
|
category: "security",
|
|
3484
3487
|
confidence: "medium",
|
|
@@ -4666,7 +4669,11 @@ var eip7702Rules = [
|
|
|
4666
4669
|
// initializer modifier, ERC1967/UUPS proxy patterns, or 'once' guard.
|
|
4667
4670
|
// Broader suppression: ERC-4337/7579 accounts use _setOwner pattern, OZ uses initializer modifier,
|
|
4668
4671
|
// proxies use ERC1967, V4 PoolManager.initialize is permissionless-by-design with noDelegateCall.
|
|
4669
|
-
|
|
4672
|
+
// Suppress when function declaration line itself contains a guard modifier
|
|
4673
|
+
// (initializer, onlyOwner, onlyProxy, noDelegateCall, payable initializer, etc.) — these
|
|
4674
|
+
// come BEFORE the opening { so the prior lookahead-after-brace missed them.
|
|
4675
|
+
// Then suppress when proxy/4337/UUPS/admin patterns appear in body.
|
|
4676
|
+
multilinePattern: /function\s+initialize\s*\([^)]*\)\s*(?:external|public)\s+(?!.*(?:initializer|reinitializer|onlyOwner|onlyProxy|onlyEntryPoint|noDelegateCall|onlyRole))[^{;]*\{(?![\s\S]{0,800}?(?:initializer|reinitializer|_disableInitializers|require\s*\([^)]*!\s*initialized|require\s*\([^)]*owner\s*==\s*address\s*\(\s*0|noDelegateCall|onlyOwner|onlyEntryPoint|onlyProxy|ERC1967|UUPS|_setOwner|_initialize|_setImplementation|_changeAdmin|EntryPoint|UserOperation|getStorage|StorageSlot|IMPLEMENTATION_SLOT|ADMIN_SLOT|require\s*\([^)]*==\s*address\s*\(\s*0\s*\)|_logic\s*\.\s*delegatecall))/,
|
|
4670
4677
|
severity: "high",
|
|
4671
4678
|
category: "solidity",
|
|
4672
4679
|
confidence: "low",
|
|
@@ -4836,8 +4843,12 @@ var hackReplayRules = [
|
|
|
4836
4843
|
title: "zkSync hack pattern \u2014 admin-only sweep/drain/rescue function",
|
|
4837
4844
|
description: "An admin-gated function with a name like sweep*, drain*, rescue*, emergencyWithdraw*, forceMint*, adminMint* is the exact category of function the zkSync airdrop attacker exploited (April 2025, $5M loss). Even with a timelock check inside, these functions are high-value targets \u2014 a compromised admin key bypasses everything. The pattern is reviewed manually because a same-line regex cannot verify whether a timelock guard is enforced.",
|
|
4838
4845
|
suggestion: "Audit this function carefully: (a) is it gated by a TimelockController contract address check, not just an onlyOwner modifier? (b) is the action bounded (max amount per call, per epoch)? (c) is there an N-of-M multisig requirement at the modifier level? If any answer is no, add it before mainnet.",
|
|
4839
|
-
|
|
4840
|
-
|
|
4846
|
+
// Suppress when function has a multi-element lock (onlyRescuer with named slot),
|
|
4847
|
+
// onlyPoolAdmin pattern (Aave), or other named-role modifiers that imply auditing-already-done.
|
|
4848
|
+
// Real catch is "onlyOwner" plain — anonymous single-role drain.
|
|
4849
|
+
multilinePattern: /function\s+(?:sweep[A-Za-z]*|drain[A-Za-z]*|rescue[A-Za-z]*|emergencyWithdraw[A-Za-z]*|forceMint[A-Za-z]*|adminMint[A-Za-z]*)\s*\([^)]*\)\s*(?:external|public)(?!.*(?:onlyRescuer|onlyPoolAdmin|onlyEmergencyAdmin|onlyRiskAdmin|onlyAclAdmin|onlyRoleAdmin|onlyConfigurator|hasRole))[^{;]*\{/,
|
|
4850
|
+
// Downgraded from high to medium: this is a "review needed" finding, not "definitely vulnerable"
|
|
4851
|
+
severity: "medium",
|
|
4841
4852
|
category: "hack-replay",
|
|
4842
4853
|
confidence: "medium",
|
|
4843
4854
|
languages: SOL
|
|
@@ -4873,9 +4884,8 @@ var hackReplayRules = [
|
|
|
4873
4884
|
// patterns that use proper auth/delay even if "timelock" keyword isn't right next to execute().
|
|
4874
4885
|
// Suppress: ERC-4337/7579 account abstraction execute(mode, data), OZ Governor, AccessManager,
|
|
4875
4886
|
// anything with auth modifiers. Real Beanstalk-shape is execute(proposalId) on a governance contract.
|
|
4876
|
-
//
|
|
4877
|
-
|
|
4878
|
-
multilinePattern: /function\s+(?:execute(?:Proposal)?|propose(?:AndExecute)?)\s*\([^)]*\)\s*(?:external|public)(?:\s+payable)?(?:\s+returns)?[^{;]*\{(?![\s\S]{0,1500}?(?:timelock|Timelock|TimelockController|queued|block\.timestamp\s*[><]=?\s*\w+\s*\+|onlyRole|onlyGovernance|onlyEntryPoint|onlyEntryPointOrSelf|_checkAuthorized|_authorizeUpgrade|AccessControl|AccessManager|Governor|IGovernor|hasRole|getMinDelay|delay\s*\(|_executeOperations|hashOperation|isOperationReady|EntryPoint|ERC7579|ERC4337|ERC7821|IAccount|_validateUserOp|UserOperation|state\s*\(\s*proposalId|_castVote|votingDelay))/,
|
|
4887
|
+
// Expanded suppression: ERC-2771 meta-tx forwarders, ERC-6551 token-bound accounts.
|
|
4888
|
+
multilinePattern: /function\s+(?:execute(?:Proposal)?|propose(?:AndExecute)?)\s*\([^)]*\)\s*(?:external|public)(?:\s+payable)?(?:\s+returns)?[^{;]*\{(?![\s\S]{0,1500}?(?:timelock|Timelock|TimelockController|queued|block\.timestamp\s*[><]=?\s*\w+\s*\+|onlyRole|onlyGovernance|onlyEntryPoint|onlyEntryPointOrSelf|_checkAuthorized|_authorizeUpgrade|AccessControl|AccessManager|Governor|IGovernor|hasRole|getMinDelay|delay\s*\(|_executeOperations|hashOperation|isOperationReady|EntryPoint|ERC7579|ERC4337|ERC7821|ERC2771|ERC6551|Forwarder|ForwardRequest|MetaTx|TokenBoundAccount|_verify|IAccount|_validateUserOp|UserOperation|state\s*\(\s*proposalId|_castVote|votingDelay))/,
|
|
4879
4889
|
severity: "critical",
|
|
4880
4890
|
category: "hack-replay",
|
|
4881
4891
|
confidence: "low",
|
|
@@ -4946,7 +4956,11 @@ var hackReplayRules = [
|
|
|
4946
4956
|
// Suppress legitimate EIP-712 / Permit / typed-data signature flows (OZ ECDSA, EIP-2612 permits,
|
|
4947
4957
|
// ERC-4337 user-op validation) which use ecrecover correctly. Only fire on bridge/oracle-shaped
|
|
4948
4958
|
// contexts where signer-set verification matters.
|
|
4949
|
-
|
|
4959
|
+
// EIP-712 / permit / typed-data patterns can appear BEFORE or AFTER ecrecover. Use a
|
|
4960
|
+
// wrapping check: require the recover call to be in a CONTEXT that contains typed-data
|
|
4961
|
+
// keywords within ~1000 chars on either side. We approximate by lookahead-only with a
|
|
4962
|
+
// bigger window AND lookbehind-by-context (check if file declares typed-data structures).
|
|
4963
|
+
multilinePattern: /(?:ecrecover|ECDSA\.recover|\w+\.recover)\s*\([\s\S]{0,400}?\)(?![\s\S]{0,1500}?(?:guardianSet|validatorSet|currentSetHash|setHash|_hashTypedDataV4|EIP712|EIP_712|DOMAIN_SEPARATOR|PERMIT_TYPEHASH|DELEGATION_TYPEHASH|ERC1271|isValidSignature|_?nonces\s*\[|_approve|_approveDelegation|_useCheckedNonce|_useNonce|require\s*\([^)]*==\s*expected))/,
|
|
4950
4964
|
severity: "high",
|
|
4951
4965
|
category: "hack-replay",
|
|
4952
4966
|
confidence: "low",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elytrasec/engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Core analysis engine for Elytra \u2014 173 detection rules including 12 famous-hack patterns and 11 rug-surface checks, static + AI scanning, scoring.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ElytraSec <hello@elytrasec.io>",
|