Skip to content

Repository files navigation

PhishGuard

ML-powered phishing URL detection using 30 heuristic features and a Random Forest classifier.

Python

Flask

scikit-learn

Docker


How it works

A URL is analysed across three layers:

  1. URL checks — pure regex and string analysis (IP address, length, shortener, symbols, port)
  2. Network checks — DNS resolution, WHOIS registration data, HTTP fetch, SSL state
  3. Content checks — HTML structure, form handlers, JavaScript patterns, redirect chains

30 features are extracted and passed to a Random Forest classifier trained on the UCI Phishing Websites dataset. The model returns a prediction (phishing / legitimate) with a confidence score.


Project structure

phishing-detector/
├── app.py                      # Flask app factory + API routes
├── config.py                   # Dev / Test / Production config classes
├── scripts/
│   └── train_model.py          # CLI trainer
├── src/
│   ├── features/
│   │   ├── extractor.py        # Orchestrates all feature modules
│   │   ├── url_checks.py       # 9 pure URL features
│   │   ├── network_checks.py   # 8 network features
│   │   └── content_checks.py   # 13 HTML/JS content features
│   ├── model/
│   │   ├── trainer.py          # Train, evaluate, save
│   │   ├── predictor.py        # Load, predict, cache
│   │   └── schemas.py          # Pydantic request/response models
│   └── utils/
│       ├── logger.py           # Structured text/JSON logging
│       └── exceptions.py       # Typed exception hierarchy
├── static/
│   ├── css/main.css
│   └── js/app.js
├── templates/
│   └── index.html
├── Dockerfile
├── docker-compose.yml
└── Makefile

Quickstart

1. Clone and install

git clone https://github.com/bavasumit/phishing-detector.git
cd phishing-detector
python -m venv .venv && source .venv/bin/activate
pip install -r requirements-dev.txt

2. Configure environment

cp .env.example .env
# Edit .env — set SECRET_KEY at minimum

3. Train the model

make train

4. Run

# Development
make dev

# Production-like (gunicorn)
make run

Open http://localhost:5000 in your browser.


📸 Screenshots

Home Page

Home Page

URL Analysis Result

URL Analysis Result


Docker

# Build and start
make build
make up

# Tail logs
make logs

# Stop
make down

The Docker image trains the model at build time so the container starts ready to serve predictions.


API

POST /api/check

Request

{ "url": "https://example.com" }

Response — legitimate

{
  "request_id":         "a1b2c3d4",
  "url":                "https://example.com",
  "domain":             "example.com",
  "prediction":         "legitimate",
  "confidence":         0.94,
  "is_phishing":        false,
  "extraction_time_ms": 1823.4,
  "features": {
    "having_IP_Address": 1,
    "URL_Length": 1,
    "SSLfinal_State": 1,
    "age_of_domain": 1
  },
  "warnings": []
}

Response — phishing

{
  "request_id":  "e5f6g7h8",
  "url":         "http://192.168.1.1/paypal-login",
  "domain":      "192.168.1.1",
  "prediction":  "phishing",
  "confidence":  0.97,
  "is_phishing": true,
  "extraction_time_ms": 2104.1,
  "features": {
    "having_IP_Address": -1,
    "SSLfinal_State": -1,
    "age_of_domain": -1,
    "DNSRecord": -1
  },
  "warnings": ["WHOIS failed for 192.168.1.1"]
}

Error responses

Code Meaning
400 Missing or malformed request body
422 Feature extraction failed
503 Model not loaded
500 Unexpected server error

GET /health

{ "status": "ok", "model_loaded": true, "environment": "production" }

Feature reference

# Feature Signal
1 having_IP_Address Host is a raw IP
2 URL_Length > 75 chars is suspicious
3 Shortening_Service bit.ly, tinyurl, etc.
4 having_At_Symbol @ hides real destination
5 double_slash_redirecting // after scheme
6 Prefix_Suffix Hyphen in domain name
7 having_Sub_Domain Deep subdomain nesting
8 HTTPS_token "https" in domain string
9 port Non-standard port
10 SSLfinal_State HTTPS + page loads
11 Domain_registration_length Expiry > 1 year
12 Favicon Loads from same domain
13 Request_URL Ratio of external resources
14 Abnormal_URL WHOIS domain mismatch
15 age_of_domain Domain > 6 months old
16 DNSRecord Domain resolves in DNS
17 Statistical_report IP/TLD in blocklist
18 URL_of_Anchor Off-domain anchor ratio
19 Links_in_tags External script/link ratio
20 SFH Form action target
21 Submitting_to_email mailto: form handler
22 Redirect HTTP redirect hop count
23 on_mouseover Status bar spoofing
24 RightClick Right-click suppressed
25 popUpWindow window.open() on load
26 Iframe Hidden iframe present
27 web_traffic Domain popularity proxy
28 Page_Rank Domain authority proxy
29 Google_Index HTTPS + loads heuristic
30 Links_pointing_to_page Anchor count in source

Feature values: 1 = legitimate signal, 0 = unknown/neutral, -1 = phishing signal.


Configuration

All values are set via environment variables. See .env.example for the full list.

Variable Default Description
FLASK_ENV development development, testing, production
SECRET_KEY auto-generated Required in production
DATASET_PATH dataset.csv Training data path
MODEL_PATH phishing_model.joblib Saved model path
REQUEST_TIMEOUT 8 Network call timeout in seconds
MAX_URL_LENGTH 2048 Maximum accepted URL length
LOG_LEVEL INFO DEBUG, INFO, WARNING, ERROR
LOG_FORMAT text text (dev) or json (prod)

Built with


About

ML-powered phishing URL detection using Flask, Random Forest, and 30 heuristic security features.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages