Fix P1: Add DoS protections to PeerID fragment handler

Critical security fix addressing Codex review feedback:

The PeerID overload of handleFragment (which is actually called by
CoreBluetooth) was missing key safety checks that existed in the
String overload:

1. Added total <= 10000 check to prevent unbounded fragment counts
2. Added cumulative size check against FileTransferLimits before
   storing each fragment
3. Prevents memory exhaustion DoS attacks via malicious fragment streams

This ensures the actually-used code path has proper bounds checking.
This commit is contained in:
jack
2025-10-18 14:24:56 +02:00
parent 7316a4a46d
commit 7ca1ff0a7e
+23 -2
View File
@@ -3414,8 +3414,8 @@ extension BLEService {
let originalType = packet.payload[12]
let fragmentData = packet.payload.suffix(from: 13)
// Sanity checks
guard total > 0 && index >= 0 && index < total else { return }
// Sanity checks - add reasonable upper bound on total to prevent DoS
guard total > 0 && total <= 10000 && index >= 0 && index < total else { return }
// Store fragment
let key = FragmentKey(sender: senderU64, id: fragU64)
@@ -3431,6 +3431,27 @@ extension BLEService {
incomingFragments[key] = [:]
fragmentMetadata[key] = (originalType, total, Date())
}
// Check cumulative size before storing this fragment
let currentSize = incomingFragments[key]?.values.reduce(0) { $0 + $1.count } ?? 0
let assemblyLimit: Int = {
if originalType == MessageType.fileTransfer.rawValue {
// Allow headroom for TLV metadata and binary framing overhead.
return FileTransferLimits.maxFramedFileBytes
}
return FileTransferLimits.maxPayloadBytes
}()
guard currentSize + fragmentData.count <= assemblyLimit else {
// Exceeds size limit - evict this assembly
SecureLogger.warning(
"🚫 Fragment assembly exceeds size limit (\(currentSize + fragmentData.count) bytes > \(assemblyLimit)), evicting",
category: .security
)
incomingFragments.removeValue(forKey: key)
fragmentMetadata.removeValue(forKey: key)
return
}
incomingFragments[key]?[index] = Data(fragmentData)
// Check if complete