Replace `NativeBufferFactory` with a more secure implementation
Description
Skia.NativeBuffer is badly designed.
The MakeFromImage function sadly returns pointers as BigInts.
https://github.com/Shopify/react-native-skia/blob/15edae07d096255fd854fb6ac1f815477194ec8c/packages/skia/cpp/api/JsiNativeBuffer.h#L20-L25
The Release function accepts a BigInt argument, which is expected to be the pointer for which the memory should be freed. It should've encapsulated the pointers and restricted this with a check to ensure the value can't be tampered with from JavaScript side.
https://github.com/Shopify/react-native-skia/blob/15edae07d096255fd854fb6ac1f815477194ec8c/packages/skia/cpp/api/JsiNativeBuffer.h#L27-L34
Ideally, the JavaScript side does not get an arbitrary way to free any hardware pointers beyond the ones it's explicitly been granted.
The recent blogpost by Google Project Zero [1] is a good example of how a simple CFRelease can be useful exploit primitive.
The gist of the attack is to rely on destructors of other Core Foundation classes to gain code execution, in the blogpost above the describe a way to create a fake malicious CFReadStream, if CFRelease is called onto these fake objects, their destructors get called and suddenly the attacker owns the control flow of the application.
In essence, this API can be abused to allocate a native buffer and we get its pointer to this memory. We fill that memory with our own fake CFReadStream, then call to release it and from there on out we control what gets executed. The memory we allocate likely isn't executable so, and there are a lot of hoops to jump through but I have a hunch that it is a viable exploitation path.
[1] https://googleprojectzero.blogspot.com/2025/03/blasting-past-webp.html
yes I can see how this is problematic, I need to think about it a little bit more.
On Mon, Apr 7, 2025 at 1:52 PM kewde @.***> wrote:
The recent blogpost by Google Project Zero [1] is a good example of how a simple CFRelease can be useful exploit primitive.
The gist of the attack is to rely on destructors of other Core Foundation classes to gain code execution, in the blogpost above the describe a way to create a fake malicious CFReadStream, if CFRelease is called onto these fake objects, their destructors get called and suddenly the attacker owns the control flow of the application.
In essence, this API can be abused to allocate a native buffer and we get its pointer to this memory. We fill that memory with our own fake `CFReadStream, then call to release it and from there on out we control what gets executed. The memory we allocate likely isn't executable so, and there are a lot of hoops to jump through but I have a hunch that it is a viable exploitation path.
[1] https://googleprojectzero.blogspot.com/2025/03/blasting-past-webp.html
— Reply to this email directly, view it on GitHub or unsubscribe. You are receiving this email because you are subscribed to this thread.
Triage notifications on the go with GitHub Mobile for iOS or Android.