Skip to content

Commit 12fffe3

Browse files
committed
Init
1 parent b5ce035 commit 12fffe3

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed

audit/FixFile.txt

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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

Comments
 (0)