Released in v1.36.0, 8 Oct 2026 Upstream bug fix in KDE Connect for Android
KDE Connect: unbounded Bluetooth packet buffer on Android
Our scanner flagged that the Bluetooth backend of KDE Connect for Android, the app that links a phone with a desktop to share notifications, files and the clipboard, buffered incoming packets without any size limit. We sent a merge request with a fix and a unit test. KDE Connect’s creator and maintainer Albert Vaca Cintora merged it the same day.
What was wrong
KDE Connect packets are JSON lines ending in \n. The receiving thread in BluetoothLink.kt appended everything it read to a StringBuilder until a newline showed up, with no upper bound. A connected peer that kept sending data without a line terminator made the app buffer all of it until it ran out of memory. Because the whole buffer was searched for \n after every 512-character read, the loop was also quadratic in the packet size.
The LAN (Wi-Fi) backend already had a guard for this: LanLink reads packets with readLineBounded() and a 32 MB limit. The Bluetooth backend did not.
The reach is limited. Bluetooth support is off by default (the setting is labelled “Enable bluetooth (beta)”), and the peer has to be a Bluetooth device already paired with the phone. The worst case is the app running out of memory, not code execution.
How it was fixed
The fix reads Bluetooth packets with the same readLineBounded() helper and the same 32 MB limit as LanLink. A packet over the limit is treated like any other read error, so the link is closed. The input is wrapped in a BufferedInputStream, as in LanLink, so byte-by-byte reads don’t take the multiplexer’s channel lock for every byte.
- val sb = StringBuilder()
try {
- val reader: Reader = InputStreamReader(input, UTF_8)
- val buf = CharArray(512)
+ val stream = BufferedInputStream(input)
while (continueAccepting) {
- while (sb.indexOf("\n") == -1 && continueAccepting) {
- ...
- sb.append(buf, 0, charsRead)
- ...
- }
+ val message = readLineBounded(stream, MAX_PACKET_SIZE)
A new unit test, BluetoothLinkTest, feeds the link 64 MB without a newline and expects it to disconnect. Before the change it timed out; after it, the full test suite passes. We tested it only with the unit test, not against a real Bluetooth peer. Albert Vaca Cintora (albertvaka) replied on the merge request:
“Thanks for catching this!”
Timeline
- 4 Oct 2026. A scan of the KDE Connect for Android tree (215 files, model gemini-3.5-flash-lite, with a project threat model) flagged the unbounded
StringBuilderinBluetoothLink.kt; triage rated it valid. - 8 Oct. We opened merge request !696 on KDE’s GitLab with the fix and the unit test. Albert Vaca Cintora merged it into master the same day as commit 11b5bde. It is part of the v1.36.0 release, tagged the same evening.
How to read this
The scanner’s triage described the attacker as “unauthenticated or remote”. Reading the code narrowed it to an opt-in backend and an already paired device, and that narrower description is what went upstream. The fix itself reuses a guard the project already had for LAN connections. Findings are leads for people, not verdicts.