-
-
Notifications
You must be signed in to change notification settings - Fork 232
Fix prototype-polluting assignments #4041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
5bbc465
to
1dc4299
Compare
How does this relate to SES? If the polluiton is on intrinsic Object.prototype, lockdown would prevent it. |
This work was motivated by our new security scanner, which highlighted this problem. I don't think the prototype pollution problem addressed here affects applications using lockdown. |
3cb8cda
to
1a32941
Compare
0e7115c
to
0ba0b11
Compare
0ba0b11
to
a2a561a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a function to check whether a single property makes sense to address this vulnerability now. It could be a bit confusing out of context, but I left some comments as to how we could explain it better.
As a future change, though, what are your thoughts about baking the check into a new function that would take an object and a property name and either set the property if it's safe or else throw an error?
@@ -194,6 +195,7 @@ export class EnsController extends BaseController< | |||
delete(chainId: Hex, ensName: string): boolean { | |||
const normalizedEnsName = normalizeEnsName(ensName); | |||
if ( | |||
!isSafeDynamicKey(chainId) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a test for this? Seems important to check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type as well as the following code assumes that chainId
is Hex
, which if true implies that isSafeDynamicKey9chainId)
would also be true.
Maybe adding a runtime-check that the chainId
actually starts with 0x
will do just as well here as well as in packages/address-book-controller/src/AddressBookController.ts
?
A function like isSafeDynamicKey
still could be useful for other cases where untrusted input string can't be assumed to be hex (indexing on method names anywhere?) but it seems like a simpler hex-prefix check will solve for all the cases covered in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's true that isValidHexAddress
for address
and isSafeChainId
for chainId
would be sufficient validation to fix the violations currently found by the scanner.
However, it seems worth it to implement more generalized blocklisting logic for this vulnerability (https://portswigger.net/web-security/prototype-pollution/preventing#sanitizing-property-keys), which will also directly placate the CodeQL scanner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we could definitely make more improvements that would ensure we can protect against this vulnerability more generally.
That seems unrelated to my comment, though. Should we add tests which attempt to call delete
with __proto__
, constructor
, and prototype
and verify that they don't do anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added tests for all three files here: a145237. Coverage is up to 100 for the three modules. I didn't test every string in the blocklist, but it seems like verifying that the validation works should be enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Testing that it essentially just gets called is fine. Do we need tests for the function itself, though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah of course I'll add that right now.
af98612
to
a2a561a
Compare
3863c6a
to
a145237
Compare
Co-authored-by: Elliot Winkel <[email protected]>
20887be
to
4d634ea
Compare
This comment was marked as resolved.
This comment was marked as resolved.
@SocketSecurity ignore npm/[email protected] New maintainer is a member of the vscode team and maintainer of 96 npm packages, many of them under the @SocketSecurity ignore npm/@lavamoat/[email protected] Internal package and maintainer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
e702cd4
to
f6c3c47
Compare
* @param key - The dynamic key to validate. | ||
* @returns Whether the given dynamic key is safe to use. | ||
*/ | ||
export function isSafeDynamicKey(key: string): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not intending to block this PR, but this seems like it could be useful for @metamask/utils
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not opposed to moving it down the line if it fits better there!
Explanation
Fixes prototype-polluting assignments by validating that dynamic-string property keys do not evaluate to
__proto__
,constructor
, orprototype
at runtime.Defines
isSafeDynamicKey
validator andPROTOTYPE_POLLUTION_BLOCKLIST
constant in@metamask/controller-utils
.References
Changelog
N/A
Checklist