d651e3c935cd

fix: Match additional URLs in Autofill origin checks (v2.3.39)

- Match Autofill entries against primary and additional URLs by registrable domain - Preserve strict lookalike rejection for additional URL aliases - Update browser parity notes for strict-origin fill matching - Verified with focused AutofillMatchTest and full testDebugUnitTest/assembleDebug/lintDebug gate

time
2026-06-26 13:26 UTC · 4 months ago
machine
koh2
parent
ba9c7c76f6c9
3 files app/build.gradle+2 −2app/src/main/java/com/peachpasswords/autofill/AutofillResponseBuilder.kt+8 −4app/src/test/java/com/peachpasswords/autofill/AutofillMatchTest.kt+15 −0
app/build.gradle+2 −2
@@ -16,8 +16,8 @@1616         applicationId "com.peachpasswords"1717         minSdk 261818         targetSdk 3519-        versionCode 23380020-        versionName "2.3.38"19+        versionCode 23390020+        versionName "2.3.39"2121 2222         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"2323         vectorDrawables {

view file

app/src/main/java/com/peachpasswords/autofill/AutofillResponseBuilder.kt+8 −4
@@ -42,12 +42,16 @@4242         if (origin.isNullOrBlank()) return MatchResult(emptyList(), entries.take(FALLBACK_LIMIT))4343         val originDomain = extractDomain(origin)4444             ?: return MatchResult(emptyList(), entries.take(FALLBACK_LIMIT))45-        val hits = entries.filter { entry ->46-            val entryDomain = extractDomain(entry.url ?: "") ?: return@filter false47-            entryDomain == originDomain48-        }45+        val hits = entries.filter { entry -> entry.matchesOriginDomain(originDomain) }4946         return MatchResult(hits = hits, rest = emptyList())5047     }48+49+    private fun VaultEntry.matchesOriginDomain(originDomain: String): Boolean =50+        sequenceOf(url)51+            .plus(additionalUrls.orEmpty().asSequence())52+            .filterNotNull()53+            .mapNotNull(::extractDomain)54+            .any { it == originDomain }5155 5256     fun menuRow(context: Context, entry: VaultEntry): RemoteViews {5357         val subtitle = entry.username ?: entry.email ?: entry.url?.let(::extractDomain) ?: ""

view file

app/src/test/java/com/peachpasswords/autofill/AutofillMatchTest.kt+15 −0
@@ -31,6 +31,21 @@3131         assertEquals(listOf(peach), result.hits)3232     }3333 34+    @Test fun additional_urls_match_registrable_domain() {35+        val peach = entry("Peach", "https://peachpasswords.com")36+            .copy(additionalUrls = listOf("https://accounts.peachpasswords.co.uk/login"))37+        val result = AutofillResponseBuilder.matchEntries(listOf(peach), "signin.peachpasswords.co.uk")38+        assertEquals(listOf(peach), result.hits)39+    }40+41+    @Test fun additional_urls_do_not_match_substring_lookalikes() {42+        val gh = entry("GitHub", null)43+            .copy(additionalUrls = listOf("https://github.com/login"))44+        val result = AutofillResponseBuilder.matchEntries(listOf(gh), "evilgithub.com")45+        assertTrue(result.hits.isEmpty())46+        assertTrue(result.rest.isEmpty())47+    }48+3449     @Test fun null_origin_yields_no_hits_only_fallback() {3550         val a = entry("A", "https://a.com")3651         val b = entry("B", "https://b.com")

view file