A production-grade MLOps pipeline for detecting phishing URLs using machine learning. Built with modular components, full experiment tracking, automated CI/CD, and cloud deployment on AWS.
| Metric | Best Run | Average (10 runs) |
|---|---|---|
| F1 Score | 99.23% | 98.26% |
| Precision | 99.05% | 97.84% |
| Recall | 99.41% | 98.68% |
Best model: sneaky-steed-391 — tracked on DagsHub MLflow
MongoDB Atlas
│
▼
┌─────────────────────────────────────────────────────────┐
│ Training Pipeline │
│ │
│ DataIngestion → DataValidation → DataTransformation │
│ │ │ │ │
│ Fetch from KS-test drift KNNImputer │
│ MongoDB detection sklearn Pipeline │
│ │ │ │
│ ▼ ▼ │
│ DataValidationArtifact .npy arrays │
│ │ │
│ ModelTrainer │
│ 5 models + GridSearchCV │
│ MLflow experiment tracking │
│ │ │
│ Best model selected │
│ Saved to final_model/ │
└─────────────────────────────────────────────────────────┘
│ │
▼ ▼
S3 (artifacts) FastAPI Inference
S3 (final_model) /predict endpoint
│
Docker → ECR
│
GitHub Actions CI/CD
(lint → ECR push → deploy)
Source: UCI ML Repository — Phishing Websites Dataset
Records: 11,055 URLs
Features: 30 ternary-encoded URL characteristics (-1 = suspicious, 0 = neutral, 1 = legitimate)
Target: Result — Phishing (1) vs Legitimate (-1)
Class balance: 55.7% phishing / 44.3% legitimate
Missing values: None
| Category | Examples |
|---|---|
| URL-based | having_IP_Address, URL_Length, Shortining_Service, having_At_Symbol |
| Domain-based | Domain_registeration_length, age_of_domain, DNSRecord |
| HTML/JS | Iframe, on_mouseover, RightClick, popUpWidnow |
| External services | Page_Rank, Google_Index, web_traffic, Statistical_report |
| SSL/Security | SSLfinal_State, HTTPS_token, Favicon |
- Connects to MongoDB Atlas via TLS/SSL
- Exports collection to pandas DataFrame
- Removes MongoDB
_idcolumn, replaces"na"strings withnp.nan - Splits into train/test sets (80/20)
- Saves as timestamped CSV artifacts
- Schema validation against
data_schema/schema.yaml - Column count and numerical column existence checks
- Kolmogorov-Smirnov drift detection across all 30 features (threshold: p < 0.05)
- Generates per-column drift report as YAML
- Blocks pipeline if critical drift detected
- KNNImputer (k=3, uniform weights) for missing value handling
- Encapsulated in a reusable sklearn
Pipelineobject - Fitted on train set only — applied to test set (no leakage)
- Saves preprocessor as
preprocessing.pklfor inference reuse - Outputs NumPy
.npyarrays for training
- Evaluates 5 classifiers with GridSearchCV (3-fold CV):
- Random Forest, Gradient Boosting, AdaBoost, Decision Tree, Logistic Regression
- Logs F1, precision, recall to MLflow on every run via DagsHub
- Selects best model by test score
- Saves
NetworkModelwrapper (preprocessor + model) for clean inference - Syncs model artifacts to S3
aws s3 syncpushes all timestamped artifacts to S3- Separate sync for pipeline artifacts vs final model
- Enables artifact versioning and rollback by timestamp
10 experiment runs tracked on DagsHub MLflow:
| Run | F1 | Precision | Recall |
|---|---|---|---|
| sneaky-steed-391 ⭐ | 0.9923 | 0.9905 | 0.9941 |
| worried-fawn-660 | 0.9917 | 0.9897 | 0.9937 |
| serious-dog-250 | 0.9915 | 0.9882 | 0.9949 |
| calm-midge-585 | 0.9910 | 0.9884 | 0.9937 |
| mercurial-swan-812 | 0.9908 | 0.9906 | 0.9910 |
| nebulous-shrew-761 | 0.9791 | 0.9719 | 0.9865 |
| adaptable-goose-482 | 0.9741 | 0.9680 | 0.9803 |
| legendary-hawk-373 | 0.9738 | 0.9659 | 0.9818 |
| silent-mule-243 | 0.9722 | 0.9668 | 0.9776 |
| rare-wasp-540 | 0.9696 | 0.9646 | 0.9748 |
📊 View all experiments on DagsHub
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Redirects to /docs |
GET |
/train |
Triggers full training pipeline |
POST |
/predict |
Accepts CSV upload, returns predictions as HTML table |
curl -X POST "http://localhost:8000/predict" \
-H "accept: application/json" \
-F "file=@your_urls.csv"Response: HTML table with original features + predicted_column (1 = phishing, 0 = legitimate)
3-stage GitHub Actions workflow (.github/workflows/main.yml):
Push to main
│
▼
Stage 1: Integration
- Checkout code
- Lint
- Unit tests
│ (on success)
▼
Stage 2: Continuous Delivery
- Configure AWS credentials
- Login to Amazon ECR
- docker build → docker push to ECR
│ (on success)
▼
Stage 3: Continuous Deployment (self-hosted runner)
- Pull latest image from ECR
- docker run -p 8080:8080
- docker system prune (cleanup)
phishing-url-detector-mlops/
│
├── .github/workflows/main.yml ← 3-stage CI/CD pipeline
├── Dockerfile ← Python 3.10-slim + AWS CLI
├── app.py ← FastAPI app (/train, /predict)
├── main.py ← Local pipeline runner
├── push_data.py ← CSV → MongoDB loader
├── requirements.txt
├── setup.py
│
├── data_schema/
│ └── schema.yaml ← Column names + types
│
├── networksecurity/
│ ├── components/
│ │ ├── data_ingestion.py ← MongoDB → CSV
│ │ ├── data_validation.py ← KS drift detection
│ │ ├── data_transformation.py ← KNNImputer pipeline
│ │ └── model_trainer.py ← 5 models + MLflow
│ ├── pipeline/
│ │ └── training_pipeline.py ← Orchestrator
│ ├── entity/
│ │ ├── config_entity.py ← Typed configs per stage
│ │ └── artifact_entity.py ← Typed artifacts per stage
│ ├── utils/
│ │ ├── main_utils/utils.py ← YAML, pickle, numpy helpers
│ │ └── ml_utils/
│ │ ├── model/estimator.py ← NetworkModel wrapper
│ │ └── metric/classification_metric.py
│ ├── cloud/s3_syncer.py ← S3 artifact sync
│ ├── constants/training_pipeline/ ← All pipeline constants
│ ├── exception/exception.py ← Custom exception + traceback
│ └── logging/logger.py ← Timestamped log files
│
└── templates/
└── table.html ← Prediction output template
- Python 3.10
- Docker
- AWS CLI configured (
aws configure) - MongoDB Atlas connection string
git clone https://github.com/Kpole95/phishing-url-detector-mlops.git
cd phishing-url-detector-mlops
pip install -r requirements.txtCreate .env:
MONGO_DB_URL=mongodb+srv://<user>:<password>@<cluster>.mongodb.net/
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
AWS_REGION=us-east-1python push_data.pypython main.pypython app.py
# API available at http://localhost:8000
# Docs at http://localhost:8000/docsdocker build -t phishing-url-detector-mlops .
docker run -p 8000:8000 \
-e MONGO_DB_URL=your_url \
-e AWS_ACCESS_KEY_ID=your_key \
-e AWS_SECRET_ACCESS_KEY=your_secret \
-e AWS_REGION=us-east-1 \
phishing-url-detector-mlops| Layer | Technology |
|---|---|
| Language | Python 3.10 |
| ML / Preprocessing | scikit-learn, pandas, numpy |
| Experiment Tracking | MLflow, DagsHub |
| API | FastAPI, Uvicorn |
| Containerization | Docker |
| Container Registry | Amazon ECR |
| Artifact Storage | Amazon S3 |
| Database | MongoDB Atlas |
| CI/CD | GitHub Actions |
| Hosting | Self-hosted runner |
Murali Krishna Pole AI/ML & MLOps Engineer LinkedIn · GitHub · DagsHub
