Skip to main content
PPPhishPondPhishing Tradecraft Intelligence

Attack · Detection · Validation

CampaignTradecraftInfrastructureDetectionResearchRadarNewsroomAboutSubscribe
CampaignTradecraftInfrastructureDetectionResearchRadarNewsroomAboutSubscribe

Research Desk

PhishPond

Phishing tradecraft research desk covering campaign analysis, adversary infrastructure, detection engineering, and validation workflows.

High signal for security teams who need tradecraft, not recycled filler.

Navigate

  • Home
  • Newsroom
  • Research
  • Subscribe

Signals

  • editorial@phishpond.dev
  • Research Mission & Ethics
  • Intel Brief
  • RSS Feed
  • Submit Research Tip
© 2026 PhishPond. Authorized security research use only.

GitHub RadarBlue team tool

cprite/phishing-detection-ext

"No Phishing" provides robust, real-time protection against phishing threats, ensuring safe browsing and enhanced internet security. Primary language: Jupyter Notebook. 16 stars.

Jupyter Notebook16 stars2 forkspushed Jul 22, 2026GPL-2.0

Project links:Open GitHub projectBack to radar

README Preview

Fetched from GitHub

<!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 --> <a name="readme-top"></a>

[![Contributors][contributors-shield]][contributors-url] [![Forks][forks-shield]][forks-url] [![Stargazers][stars-shield]][stars-url] [![Issues][issues-shield]][issues-url] [![GPL-2.0 license][license-shield]][license-url] [![LinkedIn][linkedin-shield]][linkedin-url]

<!-- PROJECT LOGO --> <br /> <div align="center"> <a href="https://github.com/cprite/phishing-detection-ext"> <img src="images/logo.png" alt="Logo" width="200" height="200"> </a>

<p align="center"> <br /> <br /> <br /> <a href="https://github.com/cprite/phishing-detection-ext/issues">Report Bug</a> · <a href="https://github.com/cprite/phishing-detection-ext/issues">Request Feature</a> </p> </div>

<!-- TABLE OF CONTENTS --> <details> <summary>Table of Contents</summary> <ol> <li> <a href="#about-the-project">About The Project</a> <ul> <li><a href="#disclaimer">[!] Disclaimer</a></li> <li><a href="#built-with">Built With</a></li> </ul> </li> <li> <a href="#getting-started">Getting Started</a> <ul> <li><a href="#retrain-the-model">Retrain the Model</a></li> </ul> </li> <li><a href="#how-it-works">How It Works</a></li> <li><a href="#model-performance">Model Performance</a></li> <li><a href="#contributing">Contributing</a></li> </ol> </details>

<!-- ABOUT THE PROJECT -->

About The Project

No Phishing is a self-contained Chrome extension that detects phishing URLs in real time. The classifier is a K-Nearest-Neighbours model implemented in pure JavaScript — no companion server, no ONNX, no WebAssembly, no data sent anywhere. It achieves 89.4% test accuracy on 11 browser-computable features, and because KNN is instance-based it learns in the browser: your corrections become new data points that immediately affect future predictions.

Disclaimer

This extension is intended as a supplementary tool for online safety. While it demonstrates high accuracy, it is not infallible. As the developer, I am not a certified cybersecurity professional, and the extension could make errors. Users are advised to exercise caution and judgment. By using "No Phishing," you acknowledge and accept responsibility for your online safety.

Built With
  • ![Python](https://www.python.org)
  • ![JavaScript](https://www.javascript.com/)
  • ![HTML](https://html.spec.whatwg.org/)
  • ![Jupyter](https://jupyterlab.readthedocs.io/en/stable)
  • ![Pandas](https://pandas.pydata.org/)
  • ![NumPy](https://numpy.org/)
  • ![scikit-learn](https://scikit-learn.org/)
  • ![Google Chrome](https://www.google.com/chrome/)
  • ![VScode](https://code.visualstudio.com/)

<p align="right">(<a href="#readme-top">back to top</a>)</p>

<!-- GETTING STARTED -->

Getting Started

No Python, no server, no setup. Just load the extension:

  1. Clone the repo
   git clone https://github.com/cprite/phishing-detection-ext.git
  1. Load the extension in Google Chrome
  • Open Google Chrome and navigate to chrome://extensions/.
  • Enable Developer mode (top-right toggle).
  • Click Load unpacked and select the cloned phishing-detection-ext directory.
  • The extension appears in your Chrome toolbar.
  1. Activate the extension
  • Click the extension icon and toggle it ON.
  • The extension will now score every page you visit locally and redirect phishing pages to a warning screen.
Rebuild the Seed Model

The seed dataset (saved_models/seed_model.json — scaled training points, labels and frozen scaler parameters) is committed and ready to use. To regenerate it:

  1. Download the dataset from Kaggle:

Web page phishing detection dataset Save it as raw_data/dataset_phishing.csv.

  1. Install build dependencies and run:
   pip install -r requirements.txt
   python export_model.py

This overwrites saved_models/seed_model.json and prints the KNN accuracy.

The original 22-feature KNN baseline and browser feature-selection rationale are documented in cyberguard_phishing_detection.ipynb.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

<!-- HOW IT WORKS -->

How It Works

Everything runs locally in your browser. No server, no network calls, no data leaves your device.

Content script (extension/content.js) — injected into every http/https page at document_idle. Sends the current URL and hyperlink count (document.querySelectorAll('a').length) to the service worker.

Service worker (extension/background.js) — receives the page report, extracts 11 features via extension/features.js, scales them with the frozen scaler and classifies with extension/knn.js over the merged seed + feedback dataset (extension/storage.js). If phishing, it redirects the tab to the built-in warning page.

KNN classifier (extension/knn.js) — a pure-JS port of scikit-learn's KNeighborsClassifier(n_neighbors=3, metric="manhattan") plus MinMaxScaler.transform. Classification is a majority vote of the 3 nearest seed points. Verified to match scikit-learn's predictions on 99.95% of the test set.

Seed dataset (saved_models/seed_model.json) — the scaled training points, labels and frozen scaler parameters, exported by export_model.py. ~7 700 points from the Hannousse & Yahiouche dataset (≈9 600 samples after cleaning).

Trusted sites — clicking Proceed on a warning adds that page's hostname to a local trusted list (chrome.storage.local). Pages on a trusted hostname are never blocked, but in the open-source build they are still scored silently in the background: a trusted host is treated as ground truth, so if the model ever flags one as phishing that verdict is fed back as a legitimate point automatically (no warning, no prompt). Manage (and remove) trusted sites from the extension popup. The list never leaves your device.

Lookalike-domain detector (extension/lookalike.js) — a deterministic rule that runs alongside the KNN, which has a blind spot on short, clean-looking brand-impersonation phishing. It checks the hostname against a list of ~50 commonly-impersonated brands with four detectors:

| Detector | Example | Confidence | Action | |---|---|---|---| | Subdomain / hyphen brand injection | apple.account-secure.com, secure-paypal.example.com, brand-bearing *.vercel.app / *.now.sh | 95% | force PHISHING | | Homoglyph swap (0↔o, 1↔l/i, rn↔m, vv↔w) | paypa1.com, m1crosoft.com, rnicrosoft.com | 90% | force PHISHING | | Typosquat — Damerau-Levenshtein 1 edit | microsfot.com, paypai.com | 90% | force PHISHING | | Typosquat — 2 edits | paypa11.com | 80% | suspect only (no block) | | TLD spoofing — brand on non-official TLD | paypal.net, netflix.org | 80% | suspect only (no block) |

A forced hit overrides the KNN vote and shows the reason on the warning page (e.g. “Domain ‘paypa1.com’ appears to be a homoglyph of ‘paypal.com’”). A suspect match (could be legitimate) never blocks on its own — it is recorded to chrome.storage.local (lookalike_suspects) and its reason rides along only if the page is blocked for another reason.

False positives are guarded several ways: a whitelist of genuine registrable domains (and common ccTLD variants) short-circuits the real brand sites and all their subdomains; brand tokens match on label/hyphen boundaries, not raw substrings (so startups never matches ups, governance never matches gov); and fuzzy matching only runs for brands ≥ 5 chars of comparable length. On a 25-URL live OpenPhish sample plus a 45-case labelled test set the detector reached 100% recall with zero false positives — but it only knows the brands in its list, and registrable-domain parsing uses a small built-in suffix list rather than the full Public Suffix List.

The 11 features — 10 lexical features derived from the URL string (length, character counts, digit ratio, suspicious-token hits) plus the page hyperlink count. WHOIS lookups, redirect-history probes, and word-length features that require a public-suffix-aware tokenizer are all omitted — they either cannot be computed client-side or cannot be reproduced in JS with exact parity to the training data. Feature formulas are verified to produce 800/800 exact-match parity with the training dataset columns.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

<!-- SELF-LEARNING -->

Self-Learning (open-source build)

KNN is instance-based — it classifies by comparing against stored points — so *adding a labelled point is retraining*. There's no offline step and no model file to rebuild: corrections take effect on the very next page you visit.

Your corrections are saved as scaled feature points in chrome.storage.local (feedback_points) and merged with the seed dataset at every inference. Two triggers (open-source build only):

  • Clicking Proceed on a warning adds the page as a legitimate point (a false positive the model got wrong).
  • Visiting a trusted host that the model flags as phishing adds it as a legitimate point automatically and silently — the trusted list is the source of truth, so a flag there is a correction signal.
  • The popup's Mark this site as phishing button adds the current tab as a phishing point (a page the model missed).

Everything stays on your device. (This is disabled in the Chrome Web Store build — see Builds.)

<a name="builds"></a>

Builds

The repository is the open-source build (extension/config.js → IS_OSS_BUILD = true): the self-learning features above are included.

The Chrome Web Store build strips them. Generate it with:

python build_cws.py

This writes dist/cws/ (load it to verify) and dist/no-phishing-cws.zip (upload it). It flips IS_OSS_BUILD = false — hiding the "Mark as phishing" button and stopping "Proceed" from adding points, so the store build never collects feedback — and leaves the Python scripts, dataset and docs out of the package.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

<!-- MODEL PERFORMANCE -->

Model Performance

Results on the held-out test set (20% split, stratified, random_state=42):

| Model | Features | Test Accuracy | Phishing Precision | Phishing Recall | |-------|----------|:---:|:---:|:---:| | KNN (k=3, manhattan) — previous server build | 22 (incl. WHOIS) | 92.65% | 93.98% | 90.89% | | KNN (k=3, manhattan) in JS — this build | 11 (browser-only) | 89.42% | 88.55% | 90.15% |

The browser build trades ~3 points of accuracy for two things the server build can't offer: it runs entirely client-side (no server, no ONNX, no WebAssembly), and it learns from your corrections in real time — every "Proceed" or "Mark as phis