fix(android): block self-package notification forwarding in allowlist mode (#99568)

Always reject the OpenClaw app package in allowsPackage, matching the
blocklist fail-closed behavior and preventing gateway/node forwarding loops.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ben.Li
2026-07-04 03:38:58 +08:00
committed by GitHub
parent 57d0747185
commit b6e6799755
4 changed files with 41 additions and 0 deletions

View File

@@ -27,6 +27,7 @@ internal data class NotificationForwardingPolicy(
val quietEnd: String,
val maxEventsPerMinute: Int,
val sessionKey: String?,
val selfPackageName: String = "",
)
/** Applies the operator-configured package allow/block list after trimming input. */
@@ -35,6 +36,10 @@ internal fun NotificationForwardingPolicy.allowsPackage(packageName: String): Bo
if (normalized.isEmpty()) {
return false
}
val self = selfPackageName.trim()
if (self.isNotEmpty() && normalized == self) {
return false
}
return when (mode) {
NotificationPackageFilterMode.Allowlist -> packages.contains(normalized)
NotificationPackageFilterMode.Blocklist -> !packages.contains(normalized)

View File

@@ -313,6 +313,7 @@ class SecurePrefs(
quietEnd = quietEnd,
maxEventsPerMinute = maxEvents.coerceAtLeast(1),
sessionKey = sessionKey,
selfPackageName = normalizedAppPackage,
)
}

View File

@@ -77,6 +77,25 @@ class NotificationForwardingPolicyTest {
assertFalse(policy.allowsPackage("com.other.app"))
}
@Test
fun allowsPackage_neverForwardsSelfPackageEvenInAllowlist() {
val policy =
NotificationForwardingPolicy(
enabled = true,
mode = NotificationPackageFilterMode.Allowlist,
packages = setOf("ai.openclaw.app", "com.other.app"),
quietHoursEnabled = false,
quietStart = "22:00",
quietEnd = "07:00",
maxEventsPerMinute = 20,
sessionKey = null,
selfPackageName = "ai.openclaw.app",
)
assertFalse(policy.allowsPackage("ai.openclaw.app"))
assertTrue(policy.allowsPackage("com.other.app"))
}
@Test
fun isWithinQuietHours_handlesWindowCrossingMidnight() {
val policy =

View File

@@ -128,4 +128,20 @@ class SecurePrefsNotificationForwardingTest {
assertFalse(policy.enabled)
assertEquals(NotificationPackageFilterMode.Blocklist, policy.mode)
}
@Test
fun getNotificationForwardingPolicy_blocksSelfPackageInAllowlistMode() {
val context = RuntimeEnvironment.getApplication()
val plainPrefs = context.getSharedPreferences("openclaw.node", Context.MODE_PRIVATE)
plainPrefs.edit().clear().commit()
val prefs = SecurePrefs(context)
prefs.setNotificationForwardingMode(NotificationPackageFilterMode.Allowlist)
prefs.setNotificationForwardingPackages(listOf("ai.openclaw.app", "com.other.app"))
val policy = prefs.getNotificationForwardingPolicy(appPackageName = "ai.openclaw.app")
assertFalse(policy.allowsPackage("ai.openclaw.app"))
assertTrue(policy.allowsPackage("com.other.app"))
}
}