|
| 1 | +OPF-2 |
| 2 | +9317d2d6c5792e900ebdcd2a72b9e5b0a80e7303 |
| 3 | +``` |
| 4 | +Removed the `_validateP256Signature` branch from `isValidSignature`. The functions `_validateEOASignature` and `_validateWebAuthnSignature` now validate only RootKey and MasterKey signatures. |
| 5 | +``` |
| 6 | + |
| 7 | +OPF-3 |
| 8 | +e4e5fdea6ef029661cb041c0c7e818aa3bc45fa7 |
| 9 | +``` |
| 10 | +The function `_revokeKey()` has been updated to include deletion of `sKey.pubKey`. |
| 11 | +``` |
| 12 | + |
| 13 | +OPF-4 |
| 14 | +c65b0a0d9812ac43f4436bb6e97742701df195ce |
| 15 | +``` |
| 16 | +The function _validateTokenSpend accepts only ERC20 tokens that are registered in the Session Key's policy, as documented in the natspec: |
| 17 | + |
| 18 | +/** |
| 19 | + |
| 20 | + * @notice Token spending limit information |
| 21 | + |
| 22 | + * @param token ERC20 Token Address |
| 23 | + |
| 24 | + * @param limit Spending Limit |
| 25 | + |
| 26 | + */ |
| 27 | + |
| 28 | +struct SpendTokenInfo { |
| 29 | + |
| 30 | + address token; |
| 31 | + |
| 32 | + uint256 limit; |
| 33 | + |
| 34 | +} |
| 35 | + |
| 36 | +According to the specification, the Session Key can interact with only one contract and one token. Supporting ERC-4626 or other extended token standards is out of scope as it would break the security model by involving three contracts in the transaction cycle. |
| 37 | + |
| 38 | +Example scenario: An owner registers a session key with AAVE v3 contract access and USDC token permissions. When the SK approves and deposits USDC to AAVE, the spending limit is decremented, and they receive aUSDC as the underlying receipt token. The session key is forbidden from accessing aUSDC since it's not the registered ERC20 token. In this case, only the owner can approve/transfer the aUSDC, while the session key could potentially trigger redemption operations. |
| 39 | + |
| 40 | +This design ensures strict access control boundaries and prevents unauthorized token manipulation beyond the explicitly granted permissions. |
| 41 | + |
| 42 | +Add to natspec more clarity about the usage of spending token policy: |
| 43 | + |
| 44 | + /** * @notice Validates a token transfer against the key’s token spend limit. * @dev Loads `value` from the last 32 bytes of `innerData` (standard ERC-20 `_transfer(address,uint256)` signature). * @dev Out of scope (not supported): Extended/alternative token interfaces where spend cannot be * inferred from the trailing 32 bytes, including but not limited to: * - ERC-777 (`send`, operator functions and hooks) * - ERC-1363 (`transferAndCall`, etc.) * - ERC-4626 vaults (`deposit`, `mint`, `withdraw`, `redeem`, etc.) * - Allowance changes (`approve`, `increaseAllowance`, `decreaseAllowance`) * - Permit-style signatures (EIP-2612) or any function where the amount is not the last arg. * Calls to those selectors MUST be blocked elsewhere (e.g., via `allowedSelectors`) because * this function will not correctly measure spend and may produce misleading deductions. * @param sKey Storage reference of the KeyData * @param innerData The full encoded call data to the token contract. * @return True if `value ≤ sKey.spendTokenInfo.limit`; false if it exceeds or is invalid. */ function _validateTokenSpend(KeyData storage sKey, bytes memory innerData) |
| 45 | +``` |
| 46 | +OPF-5 |
| 47 | +``` |
| 48 | +Position. We acknowledge the theoretical risk, but this finding is outside the security boundary Openfort can control. Under EIP-7702, delegation preserves the account’s storage across implementations by design, and any implementation the user delegates to can write to those mappings. A subsequent re-delegation to OPF cannot retroactively “clean” or prove the absence of prior storage writes by third-party code. |
| 49 | + |
| 50 | +Threat model. Openfort’s supported flow assumes users delegate to an official OPF implementation from day zero (creation of the ephemeral EOA) and remain on OPF-signed implementations. We intentionally keep a stable storage layout across OPF upgrades (e.g., v1 → v2) so that user state remains intact; changing base slots or randomizing storage would break upgrade continuity and user data. |
| 51 | + |
| 52 | +User responsibility. If a user chooses to delegate to a non-OPF implementation (or previously used a malicious implementation) before returning to OPF, any storage poisoning performed by that third party is outside OPF’s ability to prevent or detect at re-attachment time. In such cases, the responsibility for the trust decision lies with the user and their wallet UX. |
| 53 | + |
| 54 | + • Documentation that OPF security guarantees apply when delegating to official OPF implementations only. |
| 55 | + • Publish and maintain the list of official OPF implementation addresses and recommend wallets warn when delegating to unrecognized addresses. |
| 56 | + • Clarify that returning from a non-OPF implementation does not imply prior storage was trustworthy. |
| 57 | +``` |
| 58 | + |
| 59 | +OPF-6 |
| 60 | +``` |
| 61 | + In our intended flow, when a session key includes a token spend policy (SpendTokenInfo), the registration process enforces ERC-20–only usage and constrains the selectors accordingly. |
| 62 | + If SpendTokenInfo is set, the system automatically installs the canonical ERC-20 spending selectors (e.g., transfer(address,uint256), transferFrom(address,address,uint256)) and rejects any additional or unrelated selectors. |
| 63 | + These “spending selectors” are intended only for the SpendTokenInfo.token address specified in the policy. Adding another ERC-20 contract to the key’s whitelist without its own SpendTokenInfo is treated as an invalid configuration and is blocked by our off-chain validation. |
| 64 | + We will explicitly document that token spend limits apply to ERC-20 transfers only and must be paired with the token address declared in SpendTokenInfo |
| 65 | +``` |
| 66 | + |
| 67 | +OPF-7 |
| 68 | +7c4fe652d122c817a2a9e3fa69f22d73512bb7c2 |
| 69 | +``` |
| 70 | +Added function `_checkValidSignatureLength` to validate the length of `userOp.signature` based on the KeyType. This prevents gas griefing attacks where bundlers could exploit unbounded signature size during decoding. |
| 71 | + |
| 72 | +The function enforces maximum signature lengths for each key type, mitigating potential DoS vectors from malformed or excessively large signatures. |
| 73 | +``` |
| 74 | + |
| 75 | +OPF-8 |
| 76 | +ab2481c8e1f09760f42f2c5eb82245ebf9d5b45d |
| 77 | +``` |
| 78 | +Changed to non-upgradeable `EIP712` and `ReentrancyGuard` contracts to prevent storage layout conflicts with custom namespace storage layout (ERC-7201). |
| 79 | + |
| 80 | +This ensures clean separation between inherited contract storage and the account's namespaced storage pattern, eliminating potential storage collision risks. |
| 81 | +``` |
| 82 | + |
| 83 | +OPF-9 |
| 84 | +e61bef3c5a7dee1818ff7b4a22e215f81c885b7b |
| 85 | +06744188364c13ec3028f8c21f3693ea5cb7c2ac |
| 86 | +``` |
| 87 | +Added function `_masterKeyValidation` to validate master key data during initialization. This ensures master keys conform to required security parameters: |
| 88 | + |
| 89 | +/// @dev Master key must have: validUntil = max(uint48), validAfter = 0, limit = 0, whitelisting = false. |
| 90 | +function _masterKeyValidation(KeyReg calldata _kReg) internal pure { |
| 91 | + if ( |
| 92 | + _kReg.limit != 0 || |
| 93 | + _kReg.whitelisting || // must be false |
| 94 | + _kReg.validAfter != 0 || |
| 95 | + _kReg.validUntil != type(uint48).max |
| 96 | + ) revert IKeysManager.KeyManager__InvalidMasterKeyReg(_kReg); |
| 97 | +} |
| 98 | + |
| 99 | +Additionally, in the _addKey function, the field sKey.whitelisting is now enforced to be true for session keys, ensuring proper access control differentiation between master keys and session keys. |
| 100 | +``` |
| 101 | + |
| 102 | +OPF-10 |
| 103 | +ERC 7821 supoport mode=2 |
| 104 | +``` |
| 105 | + bool withOpData; |
| 106 | + /// @solidity memory-safe-assembly |
| 107 | + assembly { |
| 108 | + let len := mload(data) |
| 109 | + let flag := gt(mload(add(data, 0x20)), 0x3f) |
| 110 | + withOpData := and(eq(id, 2), and(gt(len, 0x3f), flag)) |
| 111 | + } |
| 112 | + |
| 113 | + Call[] memory calls; |
| 114 | + bytes memory opData; |
| 115 | + if (withOpData) { |
| 116 | + (calls, opData) = abi.decode(data, (Call[], bytes)); |
| 117 | + } else { |
| 118 | + calls = abi.decode(data, (Call[])); |
| 119 | + } |
| 120 | + |
| 121 | + _checkLength(calls.length); // per‑batch structural cap |
| 122 | + if (opData.length != 0) revert IExecution.OpenfortBaseAccount7702V1__UnsupportedOpData(); |
| 123 | +``` |
| 124 | + |
| 125 | +OPF-11 |
| 126 | +624080974a224e4b876eb427ecf971baed53c6bb |
| 127 | +``` |
| 128 | +fixed all |
| 129 | +``` |
| 130 | + |
| 131 | +OPF-12 |
| 132 | +624080974a224e4b876eb427ecf971baed53c6bb |
| 133 | +``` |
| 134 | +fixed |
| 135 | +``` |
| 136 | + |
| 137 | +OPF-13 |
| 138 | +9d906daa21466930cf94d259a666a2e71fb1fd43 |
| 139 | +``` |
| 140 | +fixed |
| 141 | +``` |
| 142 | + |
| 143 | +OPF-14 |
| 144 | +e19b991c0a9c06edf30ac806d384339cef36a840 |
| 145 | +``` |
| 146 | +all params for initialize() signed |
| 147 | +``` |
| 148 | + |
| 149 | +OPF-15 |
| 150 | + |
| 151 | + |
| 152 | +OPF-16 |
| 153 | + |
| 154 | + |
| 155 | +S1 |
| 156 | +f9f0978ef974e38506595c8bcc0a8a93154900b5 |
| 157 | +``` |
| 158 | +fixed |
| 159 | +``` |
| 160 | + |
| 161 | +S2 |
| 162 | +73681249694dfc172dbc818be125e341e486c8dc |
| 163 | +``` |
| 164 | +fixed |
| 165 | +``` |
| 166 | + |
| 167 | +S3 |
| 168 | +bb8f8967432850732bed13aac06f40b02046bebd |
| 169 | +``` |
| 170 | +add checker to constructor |
| 171 | + if (_lockPeriod < _recoveryPeriod || _recoveryPeriod < _securityPeriod + _securityWindow) { |
| 172 | + revert IOPF7702Recoverable.OPF7702Recoverable_InsecurePeriod(); |
| 173 | + } |
| 174 | +``` |
| 175 | + |
| 176 | +S4 |
| 177 | +8597d91f0ae783dc20d39bc156d9c3ffbddd7243 |
| 178 | +``` |
| 179 | +fixed |
| 180 | +``` |
| 181 | + |
| 182 | +S5 |
| 183 | +fe913253357eb552b5da0ce9086c30231fa13a04 |
| 184 | +``` |
| 185 | +comments and natspec fixed |
| 186 | +``` |
| 187 | + |
| 188 | +S6 |
| 189 | +9d7824e1aa4733967352b65d0bf824a9c4dab663 |
| 190 | +``` |
| 191 | +fixed |
| 192 | +``` |
| 193 | + |
| 194 | +S7 |
| 195 | +5c06ca73b5808411e883fc475923e68b47096e5c |
| 196 | +``` |
| 197 | +fixed |
| 198 | +``` |
0 commit comments