Repository structure, Git flow, docs, CI, Docker, and safe project rules.
Manifest V3 extension with popup, local URL scoring, DOM feature collection, and backend fallback behavior.
Health, analysis, and report endpoints with Pydantic schemas and tests.
Expand non-sensitive DOM signals while preserving the no-content and no-input-values boundary.
Done: added brand-impersonation detection — a visible-text (title/og:site_name/h1) brand mismatch against a curated brand-domain list shared with typosquat detection, plus a favicon-hotlinked-from-a-brand-domain check. Both are zero-network, zero-new-permission, computed purely from already-loaded DOM state. Deliberately does not do favicon byte-hash matching (would need cross-origin image fetches and a maintained hash database) or logo/image recognition.
In progress (experimental): Firefox groundwork. All source (background/service-worker.ts, content/dom-analyzer.ts, warning/overlay.ts, popup/Popup.tsx, services/settings.ts) now calls browser.* (via webextension-polyfill) instead of chrome.*, with Promise-based message listeners (return Promise<unknown> | undefined instead of sendResponse + return true/false). manifest.json adds browser_specific_settings.gecko (ignored by Chrome) and declares background.scripts next to background.service_worker — the standard cross-browser shape, since Firefox’s MV3 background is an event-page scripts entry while Chrome uses the service worker and ignores scripts. Caveat, stated plainly: this is verified only against the Chrome-targeted unit suite, the real-Chromium E2E smoke test, and the build — it has not been loaded or click-tested in a real Firefox profile, and Firefox does not support module background scripts on every 115+ build, so the event-page path may not run there yet. Treat Firefox as experimental and unverified, not a parity guarantee. Remaining work to call it done: load and click-test in a real Firefox profile and reconcile any background/module differences.
Add production-grade rate-limit handling, caching, and observability around lookups.
Improve certificate chain metadata, issuer normalization, and timeout reporting.
Done: added a Certificate Transparency freshness signal through crt.sh, guarded by PHISHLENS_ENABLE_CT_LOG_LOOKUP, as a best-effort TLS-category signal.
Done: added a sibling domain_age signal via RDAP (registration age), following the same cache/diagnostics pattern as TLS and PhishTank.
Done: trained on a real PhishTank + Tranco dataset (1200 rows, ~0.92 hold-out accuracy after fixing a URL-length dataset bias — see docs/ml-methodology.md), with versioned artifacts (git_hash, trained_at) in ml/train_model.py. A backtest of the rule-based URL heuristics (ml/evaluate_heuristics.py) confirmed typosquat/homograph detection carries most of the URL category’s weight. Temporal validation (ml/evaluate_temporal_drift.py, train on phishing >2 years old, test on phishing <14 days old) gave 0.91 accuracy, within noise of the random-split numbers. Per-prediction explainability via shap.TreeExplainer surfaces the top contributing features for each analysis, not just global feature importances. Remaining: periodic retraining as phishing patterns drift, domain-age (RDAP) as a training feature, and DOM-feature collection for the dataset (currently URL-only).
Add richer explanations, user feedback controls, and optional high-risk warning overlays.
Prepare Chrome Web Store assets, privacy policy, screenshots, and release packaging.
Monitor false positives, review threat intelligence sources, and maintain security dependencies.
Maintain a reproducible local demo, development diagnostics, request IDs, and rate-limit protections without expanding sensitive data collection.
Prepare Chrome Web Store checklist, permission documentation, demo readiness checks, and release artifacts without changing the privacy boundary.
Smaller, scoped items identified but not yet implemented:
scoring_service._score_tls), complementary to the existing expired/expiring/invalid checks.feedback_store.py only purges entries older than 30 days at process startup (schema init), not periodically while the process stays up. A long-running deployment without restarts will accumulate rows past the documented retention window.