ML-based intrusion detection for in-vehicle Controller Area Network (CAN) buses, evaluated across two real-world datasets with cross-vehicle generalization and real-time simulation.
- Overview
- Datasets
- Feature Engineering
- Models
- Results — ROAD
- Results — OTIDS
- Cross-Vehicle Generalization
- Real-Time Dashboard
- Quick Start
- Repository Structure
- Citation
- License
Modern vehicles expose CAN bus access via OBD-II ports, telematics units, and infotainment interfaces — making the bus a high-value attack target with no native authentication. This project builds a complete IDS pipeline: raw log parsing, feature engineering, model training across four classifiers, cross-vehicle transfer learning, and real-time streaming simulation.
| Script | Purpose |
|---|---|
nb1_road.py |
ROAD dataset — parse, clean, engineer features, train |
nb2_otids.py |
OTIDS/CAN-Intrusion dataset — same pipeline |
nb3_syncan.py |
SynCAN synthetic dataset — multi-class injection attacks |
nb4_cross_vehicle.py |
Cross-vehicle generalization + masquerade detection |
nb5_dashboard.py |
Real-time streaming simulation + latency benchmark |
| Dataset | Vehicle | Attack Types | Scale |
|---|---|---|---|
| ROAD | Real ORNL test vehicle | Accelerator, Correlated Spoofing, Engine Masquerade, ReverseLight Off/On, Speedometer Masquerade, Fuzzing | ~44K attack frames |
| OTIDS / CAN-Intrusion | Hyundai KIA Soul | DoS, Fuzzy, Impersonation | ~450K frames |
| SynCAN | Synthetic | DoS, Fuzzy Injection, Interval, RPM, Speed, Standstill, Systematic | Synthetic |
Datasets are not included. Download links are in the Citation section.
Features are computed per CAN frame using a sliding window over per-ID message history.
Signal statistics (ROAD)
| Feature | Description |
|---|---|
sig_mean, sig_std, sig_min, sig_max, sig_range |
Aggregate statistics across decoded signal fields |
sig_entropy |
Shannon entropy of rounded signal values |
sig_0–sig_3 |
Raw decoded signal values |
Temporal and ID-level features (all datasets)
| Feature | Description |
|---|---|
iat |
Inter-arrival time for the same arbitration ID |
iat_zscore |
Z-score of IAT relative to per-ID running statistics |
freq_dev |
Deviation from the expected per-ID transmission frequency |
hamming_dist |
Hamming distance between current and previous payload |
payload_change |
Binary — did the payload change vs. the previous message |
Rolling window features (window = 10 messages per ID)
| Feature | Description |
|---|---|
roll_iat_mean, roll_iat_std |
Rolling mean and std of inter-arrival time |
roll_entropy_mean |
Rolling mean of payload entropy |
roll_hamming_mean |
Rolling mean of Hamming distance |
Encoding — arb_id_enc: label-encoded arbitration ID
Feature count: 20 (ROAD) · 23 (OTIDS)
| Model | Configuration |
|---|---|
| Logistic Regression | Softmax multi-class, L2 regularisation |
| Random Forest | 100–300 trees, balanced class weights |
| XGBoost | Gradient-boosted trees, scale_pos_weight for imbalance |
| MLP Neural Network | 2–3 hidden layers, ReLU, dropout |
All models use RobustScaler normalisation. Class imbalance is handled via stratified subsampling and per-model weighting.
| Model | Accuracy | Precision | Recall | F1 | ROC-AUC |
|---|---|---|---|---|---|
| Logistic Regression | 56.11% | 54.76% | 70.23% | 61.54% | 56.29% |
| Random Forest | 75.27% | 73.51% | 79.00% | 76.16% | 84.54% |
| XGBoost | 74.99% | 72.69% | 80.04% | 76.19% | 83.81% |
| MLP Neural Network | 68.20% | 65.03% | 78.72% | 71.22% | 76.08% |
Per attack type
| Attack Type | Accuracy | F1 | ROC-AUC |
|---|---|---|---|
| Accelerator Attack | 76.8% | 86.7% | 54.0% |
| Correlated Spoofing | 66.8% | 66.7% | 100.0% |
| Engine Masquerade | 52.6% | 0.0% | 50.7% |
| ReverseLight Off | 61.9% | 66.5% | 70.0% |
| ReverseLight On | 60.2% | 61.4% | 71.9% |
| Speedometer Masquerade | 66.5% | 60.1% | 98.5% |
| All Metrics | ROC Curves |
|---|---|
![]() |
![]() |
| Confusion Matrices | Feature Importance |
|---|---|
![]() |
![]() |
| Model | Accuracy | Precision | Recall | F1 | ROC-AUC |
|---|---|---|---|---|---|
| Logistic Regression | 69.23% | 57.74% | 66.47% | 61.80% | 76.12% |
| Random Forest | 85.55% | 77.24% | 87.06% | 81.86% | 94.87% |
| XGBoost | 86.05% | 77.90% | 87.62% | 82.47% | 95.16% |
| MLP Neural Network | 81.04% | 80.37% | 65.33% | 72.07% | 89.67% |
Per attack type
| Attack Type | Accuracy | F1 | ROC-AUC |
|---|---|---|---|
| DoS | 99.4% | 99.4% | 100.0% |
| Fuzzy | 71.6% | 69.9% | 80.4% |
| Impersonation | 73.5% | 78.0% | 86.6% |
| Confusion Matrices | Feature Importance |
|---|---|
![]() |
![]() |
Models trained on OTIDS (KIA Soul) are evaluated against the ROAD dataset under four transfer regimes to test cross-platform robustness.
| Model | Setting | Accuracy | F1 | ROC-AUC |
|---|---|---|---|---|
| Random Forest | ROAD Direct | 76.96% | 62.89% | 86.65% |
| MLP | ROAD Direct | 78.16% | 32.60% | 75.15% |
| XGBoost | Zero-Shot | 52.47% | 25.96% | 44.35% |
| XGBoost | Few-Shot (10%) | 54.01% | 40.45% | 59.66% |
| XGBoost | Full Transfer (50%) | 55.80% | 44.12% | 64.12% |
| Cross-Vehicle Results | Masquerade Detection |
|---|---|
![]() |
![]() |
10,000 CAN frames streamed through trained models with per-frame detection, confidence scoring, and latency benchmarking.
Inference latency per frame (ms)
| Model | Mean | Median | p95 | p99 |
|---|---|---|---|---|
| MLP | 0.030 | 0.029 | 0.031 | 0.034 |
| XGBoost | 0.150 | 0.145 | 0.208 | 0.319 |
| Random Forest | 13.321 | 13.336 | 13.773 | 14.479 |
MLP and XGBoost are suitable for real-time deployment at standard CAN bus rates (500 kbps, ~5–10K frames/s). Random Forest inference is too slow for frame-level real-time use.
| Dashboard | Latency |
|---|---|
![]() |
![]() |
| Threshold Tuning | Summary |
|---|---|
![]() |
![]() |
Install dependencies
pip install xgboost scikit-learn pandas numpy matplotlib seaborn psutil joblib pyarrow tqdmConfigure paths — open each script and set DATA_DIR / OUT_DIR at the top.
Run in order
python scripts/nb1_road.py # ROAD pipeline → results/road/
python scripts/nb2_otids.py # OTIDS pipeline → results/otids/
python scripts/nb3_syncan.py # SynCAN pipeline → results/syncan/
python scripts/nb4_cross_vehicle.py # requires nb1 + nb2 outputs
python scripts/nb5_dashboard.py # requires nb2 outputsscripts/
├── nb1_road.py # ROAD dataset — full ML pipeline
├── nb2_otids.py # OTIDS dataset — full ML pipeline
├── nb3_syncan.py # SynCAN synthetic dataset — multi-class attacks
├── nb4_cross_vehicle.py # Cross-vehicle generalization + masquerade
└── nb5_dashboard.py # Real-time simulation + latency benchmark
results/
├── road/
│ ├── model_results.csv
│ ├── per_attack_type_results.csv
│ └── fig1_all_metrics · fig2_roc_curves · fig4_confusion_matrices
│ fig5_feature_importance · fig6_per_attack_type · model_comparison (PNGs)
├── otids/
│ ├── model_results.csv
│ ├── per_attack_type_results.csv
│ └── confusion_matrices · feature_importance · model_comparison (PNGs)
├── cross_vehicle/
│ ├── cross_vehicle_results.csv
│ ├── road_direct_results.csv
│ └── cross_vehicle_results · masquerade_confusion · confusion_matrices (PNGs)
└── dashboard/
├── latency_benchmark.csv
├── threshold_tuning.csv
└── realtime_dashboard · latency_comparison · threshold_tuning · summary_card (PNGs)
Model weights (.pkl) and raw data (.parquet) are not included.
ROAD Dataset
Verma, M., Bridges, R. A., Iannacone, M. D., Hollifield, S. C., & Kay, B. (2022). ROAD: The Real ORNL Automotive Dynamometer Controller Area Network Intrusion Dataset. IEEE Access. https://doi.org/10.1109/ACCESS.2022.3191586
OTIDS / CAN-Intrusion Dataset
Seo, E., Song, H. M., & Kim, H. K. (2018). GIDS: GAN Based Intrusion Detection System for In-Vehicle Network. IEEE PADS. https://doi.org/10.1109/PADS.2018.00027
SynCAN
Hanselmann, M., Strauss, T., Dormann, K., & Ulmer, H. (2020). CANet: An Unsupervised Intrusion Detection System for High Dimensional CAN Bus Data. IEEE Access. https://doi.org/10.1109/ACCESS.2020.2982544
Dataset: https://github.com/etas/SynCAN
The ROAD, OTIDS, and SynCAN datasets are subject to their respective terms of use — refer to each dataset source for details.













