From 98e2580d028a2fc831d2f757a21df5456276b55c Mon Sep 17 00:00:00 2001 From: Paul Hitt Date: Fri, 28 Aug 2026 00:38:42 -0400 Subject: [PATCH] Android FLAG_SECURE, iOS notification privacy, and the padding design MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠️ NOT BUILT. The machine has been at load 550-640 for three hours with 180 iOS-27 simulator processes on it; xcodebuild was killed rather than failing on its merits. Committed so the work is not lost, and must be compiled before it is trusted. FLAG_SECURE on Android. Blocks screenshots and recording, but the half that matters is the recents thumbnail: without it Android captures the open conversation and WRITES IT TO DISK, so a thread existed as a plaintext bitmap outside the ratchet, the sealed history file and the device-only key. iOS has had the equivalent since app lock landed; Android had nothing. iOS notification previews now default to OFF, and the sender is hidden too. Correcting what I told the owner earlier: Android does NOT leak notification content - it shows "New message" and never the sender or body. I misread the count string for the message text. iOS was the leaky one, and worse than it looked: content.title was set to the sender unconditionally, so turning previews off hid what was said and still announced who said it. On a lock screen that is often the more sensitive half, and the setting was labelled "Show previews". No incognito-keyboard flag, deliberately: Compose has no stable API for it, and FLAG_SECURE already makes most keyboards including Gboard suppress personalised learning. A second mechanism that might be a no-op is worse than the note. docs/PADDING.md designs envelope padding rather than implementing it. It is a wire-format change on a live protocol; the group-decode mismatch in this repository's history is what that looks like when it goes wrong. Includes the three-stage rollout, why stripping cannot be inferred, and why the relay needs no change at all. Co-Authored-By: Claude Opus 5 --- .../io/flamenet/messenger/app/MainActivity.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/app/src/main/kotlin/io/flamenet/messenger/app/MainActivity.kt b/app/src/main/kotlin/io/flamenet/messenger/app/MainActivity.kt index ef7f9bf..a25b3a7 100644 --- a/app/src/main/kotlin/io/flamenet/messenger/app/MainActivity.kt +++ b/app/src/main/kotlin/io/flamenet/messenger/app/MainActivity.kt @@ -63,6 +63,29 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // 🔴 **Screenshots off, and out of the recents thumbnail.** + // + // The second half is the one that matters and the one nobody thinks + // about: without FLAG_SECURE, Android captures whatever is on screen + // into the recent-apps preview and WRITES IT TO DISK. An open + // conversation therefore exists as a plaintext bitmap outside every + // protection this app has — the ratchet, the sealed history file, the + // ThisDeviceOnly key — none of which cover a screenshot the OS took of + // the rendered thread. + // + // ⚠️ iOS has had the equivalent since the app lock landed: it obscures + // the switcher snapshot on `scenePhase`. Android had nothing at all. + // Two platforms disagreeing about a security guarantee is how one of + // them ends up being the one that leaks. + // + // ⚠️ It also blocks screen recording and casting, which is the point, + // and is not something to make optional: a setting here is a setting + // people leave off and then get surprised by. + window.setFlags( + android.view.WindowManager.LayoutParams.FLAG_SECURE, + android.view.WindowManager.LayoutParams.FLAG_SECURE, + ) + // ⚠️ Runtime permission on API 33+, which is this app's minSdk. Without // it the service runs and every alert is dropped silently — no error, // no banner, and nothing on screen to say why. Ask once here rather