8a823f06122b

broaden policy scraper: deeper DOM walk, label/div selectors, range/exact/min-only pattern forms, between/exactly text phrases

time
2026-05-05 16:11 UTC · 5 months ago
machine
koh2
parent
d08bf4e3dd8a
3 files manifest.firefox.json+1 −1manifest.json+1 −1src/content/policy.ts+23 −8
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach",4-  "version": "2.30.2",4+  "version": "2.32.0",55   "description": "Zero-knowledge password manager",66   "browser_specific_settings": {77     "gecko": {

view file

manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach",4-  "version": "2.31.0",4+  "version": "2.32.0",55   "description": "Zero-knowledge password manager",66   "action": {77     "default_popup": "src/popup/index.html",

view file

src/content/policy.ts+23 −8
@@ -27,11 +27,11 @@2727     if (desc) return desc.textContent ?? "";2828   }2929   let node: Element | null = el;30-  for (let i = 0; i < 3; i++) {30+  for (let i = 0; i < 5; i++) {3131     node = node?.parentElement ?? null;3232     if (!node) break;3333     const hints = node.querySelectorAll(34-      "p, span, li, small, .hint, .requirement, .password-rule"34+      "p, span, li, small, label, div, .hint, .requirement, .password-rule, .password-hint, .password-rules, .field-hint, .helper-text, .input-hint"3535     );3636     if (hints.length > 0) {3737       return Array.from(hints).map((h) => h.textContent).join(" ");@@ -50,18 +50,33 @@5050   if (maxLen > 0) policy.maxLength = maxLen;5151   if (passwordField?.pattern) {5252     const pat = passwordField.pattern;53-    const minMatch = pat.match(/\{(\d+),/);54-    const maxMatch = pat.match(/,(\d+)\}/);55-    if (minMatch) policy.minLength = parseInt(minMatch[1]!);56-    if (maxMatch) policy.maxLength = parseInt(maxMatch[1]!);53+    // .{N,M} — range; .{N,} — min only; .{N} — exact54+    const rangeMatch = pat.match(/\{(\d+),(\d+)\}/);55+    const minOnlyMatch = pat.match(/\{(\d+),\}/);56+    const exactMatch = pat.match(/\{(\d+)\}/);57+    if (rangeMatch) {58+      policy.minLength = parseInt(rangeMatch[1]!);59+      policy.maxLength = parseInt(rangeMatch[2]!);60+    } else if (minOnlyMatch) {61+      policy.minLength = parseInt(minOnlyMatch[1]!);62+    } else if (exactMatch) {63+      policy.minLength = parseInt(exactMatch[1]!);64+      policy.maxLength = parseInt(exactMatch[1]!);65+    }5766   }5867 5968   const text = extractNearbyText(passwordField);6069 61-  const minMatch = text.match(/(?:at least|minimum|min)[^\d]*(\d+)/i);62-  const maxMatch = text.match(/(?:at most|maximum|max|up to|cannot exceed|must not exceed|no more than)[^\d]*(\d+)/i);70+  const minMatch = text.match(/(?:at least|minimum|min(?:imum)?|must be (?:at least )?)(?:\D*?)(\d+)/i);71+  const maxMatch = text.match(/(?:at most|maximum|max(?:imum)?|up to|cannot exceed|must not exceed|no more than|must be (?:no more than |at most )?)(?:\D*?)(\d+)/i);72+  const betweenMatch = text.match(/between\D*?(\d+)\D+?(\d+)/i);73+  const exactMatch2 = text.match(/(?:exactly|must be)\D*?(\d+)\s*characters?/i);74+  if (betweenMatch && !policy.minLength) policy.minLength = parseInt(betweenMatch[1]!);75+  if (betweenMatch && !policy.maxLength) policy.maxLength = parseInt(betweenMatch[2]!);6376   if (minMatch && !policy.minLength) policy.minLength = parseInt(minMatch[1]!);6477   if (maxMatch && !policy.maxLength) policy.maxLength = parseInt(maxMatch[1]!);78+  if (exactMatch2 && !policy.minLength) policy.minLength = parseInt(exactMatch2[1]!);79+  if (exactMatch2 && !policy.maxLength) policy.maxLength = parseInt(exactMatch2[1]!);6580 6681   if (/no\s+(?:special|symbol)/i.test(text)) policy.forbidsSymbols = true;6782   if (/(?:special|symbol|punctuation)/i.test(text)) policy.requiresSymbols = true;

view file