From 545cce08024f46d21370927ceada2d230be01542 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Sun, 19 Apr 2026 11:14:27 +0200 Subject: [PATCH] Add browser extension false-positive field exclusion logic (#1935) --- .../src/utils/formDetector/FieldPatterns.ts | 35 ++++++++++ .../src/utils/formDetector/FormDetector.ts | 70 ++++++++++++++++++- 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/apps/browser-extension/src/utils/formDetector/FieldPatterns.ts b/apps/browser-extension/src/utils/formDetector/FieldPatterns.ts index 846beaa24..bc968aab7 100644 --- a/apps/browser-extension/src/utils/formDetector/FieldPatterns.ts +++ b/apps/browser-extension/src/utils/formDetector/FieldPatterns.ts @@ -44,6 +44,13 @@ export type EmailVerificationPatterns = { changeEmail: RegExp[]; } +/** + * Type for field exclusion patterns. These patterns are used to exclude fields from autofill detection. + * Fields matching these patterns should not trigger the autofill popup, even if they match + * other field patterns (like username or email). + */ +export type FieldExclusionPatterns = string[]; + /** * English field patterns to detect English form fields. */ @@ -100,6 +107,16 @@ export const EnglishEmailVerificationPatterns: EmailVerificationPatterns = { ] }; +/** + * English field exclusion patterns. These patterns identify fields that should NOT trigger autofill, + * such as search boxes and filters. These are commonly found in admin panels, + * data tables, and navigation areas where autofill would be inappropriate. + */ +export const EnglishFieldExclusionPatterns: FieldExclusionPatterns = [ + 'search', 'find', 'lookup', 'searchbox', 'search-box', 'searchfield', 'search-field', 'searchinput', 'search-input', 'searchquery', 'search-query', + 'filter', 'filterable', 'filterinput', 'filter-input', 'filterfield', 'filter-field', 'filterbox', 'filter-box' +]; + /** * English words to filter out from page titles during autofill matching to * prevent generic words from causing false positives. @@ -158,6 +175,14 @@ export const DutchFieldPatterns: FieldPatterns = { totp: ['verificatiecode', 'eenmalig', 'authenticatie', 'tweefactor', 'beveiligingscode'] }; +/** + * Dutch field exclusion patterns. These patterns identify fields that should NOT trigger autofill. + */ +export const DutchFieldExclusionPatterns: FieldExclusionPatterns = [ + 'zoeken', 'zoek', 'zoekveld', 'zoek-veld', 'zoekinput', 'zoek-input', 'zoekbox', 'zoek-box', + 'filter', 'filteren', 'filterveld', 'filter-veld', 'filterinput', 'filter-input' +]; + /** * Dutch gender option patterns */ @@ -314,3 +339,13 @@ export const CombinedEmailVerificationPatterns: EmailVerificationPatterns = { ...DutchEmailVerificationPatterns.changeEmail ] }; + +/** + * Combined field exclusion patterns from all supported languages. These patterns identify fields + * that should NOT trigger autofill, regardless of whether they match other field patterns. + * This prevents false positives on search boxes and filters commonly found + * in admin panels, data tables, and navigation areas. + */ +export const CombinedFieldExclusionPatterns: FieldExclusionPatterns = [ + ...new Set([...EnglishFieldExclusionPatterns, ...DutchFieldExclusionPatterns]) +]; diff --git a/apps/browser-extension/src/utils/formDetector/FormDetector.ts b/apps/browser-extension/src/utils/formDetector/FormDetector.ts index 91e69cf7b..83cadbb3c 100644 --- a/apps/browser-extension/src/utils/formDetector/FormDetector.ts +++ b/apps/browser-extension/src/utils/formDetector/FormDetector.ts @@ -1,4 +1,4 @@ -import { CombinedEmailVerificationPatterns, CombinedFieldPatterns, CombinedGenderOptionPatterns, CombinedStopWords } from "./FieldPatterns"; +import { CombinedEmailVerificationPatterns, CombinedFieldExclusionPatterns, CombinedFieldPatterns, CombinedGenderOptionPatterns, CombinedStopWords } from "./FieldPatterns"; import { DetectedFieldType, FormFields } from "./types/FormFields"; /** @@ -210,6 +210,66 @@ export class FormDetector { return wrapper; } + /** + * Check if an input field matches exclusion patterns (search, filter, query fields). + * These fields should not trigger autofill even if they match other patterns. + * Uses whole-word matching to avoid false positives (e.g., "date" shouldn't match "birthdate"). + * @param input - The input element to check. + * @returns True if the field matches exclusion patterns and should be excluded from autofill. + */ + private matchesExclusionPatterns(input: HTMLInputElement): boolean { + // Collect all text attributes to check + const attributesToCheck = [ + input.id, + input.getAttribute('name'), + input.getAttribute('placeholder'), + input.getAttribute('class'), + input.getAttribute('aria-label') + ] + .map(a => a?.toLowerCase() ?? '') + .filter(a => a.length > 0); + + // Also check associated labels + if (input.id || input.getAttribute('name')) { + const label = this.document.querySelector(`label[for="${input.id || input.getAttribute('name')}"]`); + if (label) { + attributesToCheck.push(label.textContent?.toLowerCase() ?? ''); + } + } + + // Use the combined exclusion patterns + const allExclusionPatterns = CombinedFieldExclusionPatterns; + + /* + * Check if any attribute contains any exclusion pattern + * Use whole-word or compound-word matching to avoid false positives + */ + for (const attr of attributesToCheck) { + for (const pattern of allExclusionPatterns) { + /* + * Check for whole-word matches or compound word matches (search-box, searchInput, etc.) + * Pattern must be: + * - At the start: "search", "searchbox", "search-box", "search_box" + * - In the middle: "user-search", "data_search" + * - At the end: "quick-search" + * But NOT within another word: "research" (re-search), "birthdate" (date) + * + * Word boundaries: start of string, space, hyphen, underscore, or transition from lowercase to uppercase + */ + const wordBoundaryPattern = new RegExp( + `(^|[\\s\\-_]|(?<=[a-z])(?=[A-Z]))${pattern}($|[\\s\\-_]|(?<=[a-z])(?=[A-Z]))`, + 'i' + ); + + if (wordBoundaryPattern.test(attr)) { + return true; + } + } + } + + return false; + } + /** * Check if an input field is likely a fake/honeypot field used to prevent autofill. * These fields are intentionally hidden from users but present in the DOM. @@ -543,6 +603,14 @@ export class FormDetector { continue; } + /* + * Skip fields that match exclusion patterns (search, filter, query fields). + * These should never trigger autofill, even if they match other patterns. + */ + if (this.matchesExclusionPatterns(input as HTMLInputElement)) { + continue; + } + /* * Skip fake/honeypot fields (e.g., fields with "fake" in name/id, tabindex="-1", etc.) */