Conversation
|
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3903 +/- ##
=======================================
Coverage 98.56% 98.56%
=======================================
Files 426 427 +1
Lines 12316 12344 +28
Branches 1935 1939 +4
=======================================
+ Hits 12139 12167 +28
Misses 177 177 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| endowmentGetter: (_getterOptions?: EndowmentGetterParams) => null, | ||
| validator: createGenericPermissionValidator([ | ||
| { type: SnapCaveatType.KeyringOrigin }, | ||
| { type: SnapCaveatType.KeyringCapabilities, optional: true }, |
There was a problem hiding this comment.
Did we decide on behaviour if this is not defined? Since we are making it optional
There was a problem hiding this comment.
Yes, omission of the capabilities is an implicit indication of using keyring v1
| const caveats = []; | ||
|
|
||
| caveats.push({ | ||
| type: SnapCaveatType.KeyringOrigin, | ||
| value: { allowedOrigins: value.allowedOrigins }, | ||
| }); | ||
|
|
||
| if (hasProperty(value, 'capabilities')) { | ||
| caveats.push({ | ||
| type: SnapCaveatType.KeyringCapabilities, | ||
| value: { capabilities: value.capabilities }, | ||
| }); | ||
| } | ||
|
|
||
| return { caveats: caveats as unknown as NonEmptyArray<CaveatConstraint> }; |
There was a problem hiding this comment.
There's probably a better way of doing this that doesn't require the ugly type cast at the end
There was a problem hiding this comment.
Hmm, I followed the pattern Frederik suggested: #3903 (comment)
There was a problem hiding this comment.
You can do that to remove the need to cast to unkown :
| const caveats = []; | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringOrigin, | |
| value: { allowedOrigins: value.allowedOrigins }, | |
| }); | |
| if (hasProperty(value, 'capabilities')) { | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringCapabilities, | |
| value: { capabilities: value.capabilities }, | |
| }); | |
| } | |
| return { caveats: caveats as unknown as NonEmptyArray<CaveatConstraint> }; | |
| const caveats = []; | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringOrigin, | |
| value, | |
| }); | |
| if (value.capabilities) { | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringCapabilities, | |
| value, | |
| }); | |
| } | |
| return { caveats: caveats as NonEmptyArray<CaveatConstraint> }; |
Also I've noticed in Frederik's example that the value is extracted so I don't know if we should do that instead :
| const caveats = []; | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringOrigin, | |
| value: { allowedOrigins: value.allowedOrigins }, | |
| }); | |
| if (hasProperty(value, 'capabilities')) { | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringCapabilities, | |
| value: { capabilities: value.capabilities }, | |
| }); | |
| } | |
| return { caveats: caveats as unknown as NonEmptyArray<CaveatConstraint> }; | |
| const caveats = []; | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringOrigin, | |
| value: value.allowedOrigins, | |
| }); | |
| if (value.capabilities) { | |
| caveats.push({ | |
| type: SnapCaveatType.KeyringCapabilities, | |
| value: value.capabilities, | |
| }); | |
| } | |
| return { caveats: caveats as NonEmptyArray<CaveatConstraint> }; |
Both works TBH, I'm just wondering why there's a difference between the two
There was a problem hiding this comment.
The second one seems to be the standard btw
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| caveats.push({ | ||
| type: SnapCaveatType.KeyringCapabilities, | ||
| value: value.capabilities, | ||
| }); |
There was a problem hiding this comment.
Caveat values missing required wrapper object keys
High Severity
getKeyringCaveatMapper stores unwrapped values for both caveats. For KeyringOrigin, it sets value: value.allowedOrigins (a bare array) instead of value: { allowedOrigins: value.allowedOrigins }. For KeyringCapabilities, it sets value: value.capabilities (the inner object) instead of value: { capabilities: value.capabilities }. This causes validateCaveatOrigins to reject the value (arrays fail isPlainObject) and assertIsKeyringCapabilities to reject the value (missing the capabilities key expected by KeyringCapabilitiesStruct). The tests confirm the expected shape includes the wrapper keys, and the getters (getKeyringCaveatOrigins, getKeyringCaveatCapabilities) return caveat.value typed with those wrapper shapes.


Adding capabilities to the keyring endowment as part of keyring v2 work (https://github.com/MetaMask/decisions/blob/main/decisions/core/0006-keyring-interface.md)
Note
Medium Risk
Expands the
endowment:keyringpermission/manifest surface area by introducing a new caveat and validation logic, which could affect permission parsing and compatibility for existing snaps if mis-specified.Overview
Adds
keyringCapabilitiesas an optional caveat forendowment:keyring, allowing snap manifests/initial permissions to declare a structuredcapabilitiesobject.Updates the keyring endowment builder and mapper to emit/accept the new caveat, adds
getKeyringCaveatCapabilitiesfor retrieving it from granted permissions, and extends caveat/manifest validation via a newKeyringCapabilitiesStruct+assertIsKeyringCapabilitiesexport (with accompanying tests and snapshot updates).Written by Cursor Bugbot for commit 00733ae. This will update automatically on new commits. Configure here.