aiwaf 0.1.9.0.1__tar.gz → 0.1.9.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiwaf might be problematic. Click here for more details.

Files changed (33) hide show
  1. {aiwaf-0.1.9.0.1/aiwaf.egg-info → aiwaf-0.1.9.0.3}/PKG-INFO +21 -2
  2. aiwaf-0.1.9.0.1/PKG-INFO → aiwaf-0.1.9.0.3/README.md +19 -21
  3. aiwaf-0.1.9.0.3/aiwaf/__init__.py +6 -0
  4. aiwaf-0.1.9.0.3/aiwaf/management/commands/regenerate_model.py +79 -0
  5. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/middleware.py +42 -4
  6. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/trainer.py +21 -4
  7. aiwaf-0.1.9.0.1/README.md → aiwaf-0.1.9.0.3/aiwaf.egg-info/PKG-INFO +40 -0
  8. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf.egg-info/SOURCES.txt +1 -0
  9. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf.egg-info/requires.txt +1 -1
  10. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/pyproject.toml +2 -2
  11. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/setup.py +2 -2
  12. aiwaf-0.1.9.0.1/aiwaf/__init__.py +0 -24
  13. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/LICENSE +0 -0
  14. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/apps.py +0 -0
  15. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/blacklist_manager.py +0 -0
  16. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/decorators.py +0 -0
  17. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/management/__init__.py +0 -0
  18. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/management/commands/__init__.py +0 -0
  19. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/management/commands/add_ipexemption.py +0 -0
  20. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/management/commands/aiwaf_diagnose.py +0 -0
  21. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/management/commands/aiwaf_logging.py +0 -0
  22. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/management/commands/aiwaf_reset.py +0 -0
  23. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/management/commands/detect_and_train.py +0 -0
  24. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/middleware_logger.py +0 -0
  25. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/models.py +0 -0
  26. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/resources/model.pkl +0 -0
  27. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/storage.py +0 -0
  28. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/templatetags/__init__.py +0 -0
  29. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/templatetags/aiwaf_tags.py +0 -0
  30. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf/utils.py +0 -0
  31. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf.egg-info/dependency_links.txt +0 -0
  32. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/aiwaf.egg-info/top_level.txt +0 -0
  33. {aiwaf-0.1.9.0.1 → aiwaf-0.1.9.0.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.9.0.1
3
+ Version: 0.1.9.0.3
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -12,7 +12,7 @@ License-File: LICENSE
12
12
  Requires-Dist: Django>=3.2
13
13
  Requires-Dist: numpy>=1.21
14
14
  Requires-Dist: pandas>=1.3
15
- Requires-Dist: scikit-learn>=1.0
15
+ Requires-Dist: scikit-learn<2.0,>=1.0
16
16
  Requires-Dist: joblib>=1.1
17
17
  Dynamic: author
18
18
  Dynamic: home-page
@@ -371,6 +371,7 @@ MIDDLEWARE = [
371
371
 
372
372
  **Common Issues:**
373
373
  - **AppRegistryNotReady Error**: Fixed in v0.1.9.0.1 - update with `pip install --upgrade aiwaf`
374
+ - **Scikit-learn Version Warnings**: Fixed in v0.1.9.0.3 - regenerate model with `python manage.py regenerate_model`
374
375
  - Missing Django: `pip install Django`
375
376
  - Old AI-WAF version: `pip install --upgrade aiwaf`
376
377
  - Missing migrations: `python manage.py migrate`
@@ -388,6 +389,24 @@ python manage.py detect_and_train
388
389
  1. Read access logs (incl. rotated or gzipped) **OR** AI-WAF middleware CSV logs
389
390
  2. Auto‑block IPs with ≥ 6 total 404s
390
391
  3. Extract features & train IsolationForest
392
+ 4. Save `model.pkl` with current scikit-learn version
393
+
394
+ ### Model Regeneration
395
+
396
+ If you see scikit-learn version warnings, regenerate the model:
397
+
398
+ ```bash
399
+ # Quick model regeneration (recommended)
400
+ python manage.py regenerate_model
401
+
402
+ # Full retraining with fresh data
403
+ python manage.py detect_and_train
404
+ ```
405
+
406
+ **Benefits:**
407
+ - ✅ Eliminates version compatibility warnings
408
+ - ✅ Uses current scikit-learn optimizations
409
+ - ✅ Maintains same protection level
391
410
  4. Save `model.pkl`
392
411
  5. Extract top 10 dynamic keywords from 4xx/5xx
393
412
  6. Remove any keywords associated with newly exempt paths
@@ -1,24 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: aiwaf
3
- Version: 0.1.9.0.1
4
- Summary: AI-powered Web Application Firewall
5
- Home-page: https://github.com/aayushgauba/aiwaf
6
- Author: Aayush Gauba
7
- Author-email: Aayush Gauba <gauba.aayush@gmail.com>
8
- License: MIT
9
- Requires-Python: >=3.8
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: Django>=3.2
13
- Requires-Dist: numpy>=1.21
14
- Requires-Dist: pandas>=1.3
15
- Requires-Dist: scikit-learn>=1.0
16
- Requires-Dist: joblib>=1.1
17
- Dynamic: author
18
- Dynamic: home-page
19
- Dynamic: license-file
20
- Dynamic: requires-python
21
-
22
1
 
23
2
  # AI‑WAF
24
3
 
@@ -371,6 +350,7 @@ MIDDLEWARE = [
371
350
 
372
351
  **Common Issues:**
373
352
  - **AppRegistryNotReady Error**: Fixed in v0.1.9.0.1 - update with `pip install --upgrade aiwaf`
353
+ - **Scikit-learn Version Warnings**: Fixed in v0.1.9.0.3 - regenerate model with `python manage.py regenerate_model`
374
354
  - Missing Django: `pip install Django`
375
355
  - Old AI-WAF version: `pip install --upgrade aiwaf`
376
356
  - Missing migrations: `python manage.py migrate`
@@ -388,6 +368,24 @@ python manage.py detect_and_train
388
368
  1. Read access logs (incl. rotated or gzipped) **OR** AI-WAF middleware CSV logs
389
369
  2. Auto‑block IPs with ≥ 6 total 404s
390
370
  3. Extract features & train IsolationForest
371
+ 4. Save `model.pkl` with current scikit-learn version
372
+
373
+ ### Model Regeneration
374
+
375
+ If you see scikit-learn version warnings, regenerate the model:
376
+
377
+ ```bash
378
+ # Quick model regeneration (recommended)
379
+ python manage.py regenerate_model
380
+
381
+ # Full retraining with fresh data
382
+ python manage.py detect_and_train
383
+ ```
384
+
385
+ **Benefits:**
386
+ - ✅ Eliminates version compatibility warnings
387
+ - ✅ Uses current scikit-learn optimizations
388
+ - ✅ Maintains same protection level
391
389
  4. Save `model.pkl`
392
390
  5. Extract top 10 dynamic keywords from 4xx/5xx
393
391
  6. Remove any keywords associated with newly exempt paths
@@ -0,0 +1,6 @@
1
+ default_app_config = "aiwaf.apps.AiwafConfig"
2
+
3
+ __version__ = "0.1.9.0.3"
4
+
5
+ # Note: Middleware classes are available from aiwaf.middleware
6
+ # Import them only when needed to avoid circular imports during Django app loading
@@ -0,0 +1,79 @@
1
+ from django.core.management.base import BaseCommand
2
+ import os
3
+ import warnings
4
+
5
+ class Command(BaseCommand):
6
+ help = 'Regenerate AI-WAF model with current scikit-learn version'
7
+
8
+ def add_arguments(self, parser):
9
+ parser.add_argument(
10
+ '--force',
11
+ action='store_true',
12
+ help='Force regeneration even if model exists',
13
+ )
14
+
15
+ def handle(self, *args, **options):
16
+ self.stdout.write(self.style.HTTP_INFO("🔄 AI-WAF Model Regeneration"))
17
+ self.stdout.write("")
18
+
19
+ # Check current sklearn version
20
+ try:
21
+ import sklearn
22
+ self.stdout.write(f"Current scikit-learn version: {sklearn.__version__}")
23
+ except ImportError:
24
+ self.stdout.write(self.style.ERROR("❌ scikit-learn not available"))
25
+ self.stdout.write("Install with: pip install scikit-learn")
26
+ return
27
+
28
+ # Check if model exists
29
+ from aiwaf.trainer import MODEL_PATH
30
+ model_exists = os.path.exists(MODEL_PATH)
31
+
32
+ if model_exists and not options['force']:
33
+ self.stdout.write(f"Model exists at: {MODEL_PATH}")
34
+
35
+ # Try to load and check version
36
+ try:
37
+ import joblib
38
+ with warnings.catch_warnings():
39
+ warnings.filterwarnings("ignore", category=UserWarning, module="sklearn.base")
40
+ model_data = joblib.load(MODEL_PATH)
41
+
42
+ if isinstance(model_data, dict) and 'sklearn_version' in model_data:
43
+ stored_version = model_data['sklearn_version']
44
+ if stored_version == sklearn.__version__:
45
+ self.stdout.write(self.style.SUCCESS("✅ Model is up-to-date"))
46
+ return
47
+ else:
48
+ self.stdout.write(f"⚠️ Model version mismatch:")
49
+ self.stdout.write(f" Stored: {stored_version}")
50
+ self.stdout.write(f" Current: {sklearn.__version__}")
51
+ else:
52
+ self.stdout.write("⚠️ Legacy model format detected")
53
+
54
+ except Exception as e:
55
+ self.stdout.write(f"⚠️ Could not check model: {e}")
56
+
57
+ self.stdout.write("")
58
+ self.stdout.write("Regenerating model to fix version compatibility...")
59
+
60
+ # Regenerate model
61
+ self.stdout.write("🚀 Starting model training...")
62
+
63
+ try:
64
+ from aiwaf.trainer import train
65
+ train()
66
+ self.stdout.write("")
67
+ self.stdout.write(self.style.SUCCESS("✅ Model regenerated successfully!"))
68
+ self.stdout.write("")
69
+ self.stdout.write("The model is now compatible with your current scikit-learn version.")
70
+ self.stdout.write("Version warnings should no longer appear.")
71
+
72
+ except Exception as e:
73
+ self.stdout.write("")
74
+ self.stdout.write(self.style.ERROR(f"❌ Model regeneration failed: {e}"))
75
+ self.stdout.write("")
76
+ self.stdout.write("Possible solutions:")
77
+ self.stdout.write("1. Check that you have log data available")
78
+ self.stdout.write("2. Verify AIWAF_ACCESS_LOG setting")
79
+ self.stdout.write("3. Run 'python manage.py detect_and_train' for full training")
@@ -25,7 +25,43 @@ MODEL_PATH = getattr(
25
25
  "AIWAF_MODEL_PATH",
26
26
  os.path.join(os.path.dirname(__file__), "resources", "model.pkl")
27
27
  )
28
- MODEL = joblib.load(MODEL_PATH)
28
+
29
+ def load_model_safely():
30
+ """Load the AI model with version compatibility checking."""
31
+ import warnings
32
+ import sklearn
33
+
34
+ try:
35
+ # Suppress sklearn version warnings temporarily
36
+ with warnings.catch_warnings():
37
+ warnings.filterwarnings("ignore", category=UserWarning, module="sklearn.base")
38
+ model_data = joblib.load(MODEL_PATH)
39
+
40
+ # Handle both old format (direct model) and new format (with metadata)
41
+ if isinstance(model_data, dict) and 'model' in model_data:
42
+ # New format with metadata
43
+ model = model_data['model']
44
+ stored_version = model_data.get('sklearn_version', 'unknown')
45
+ current_version = sklearn.__version__
46
+
47
+ if stored_version != current_version:
48
+ print(f"ℹ️ Model was trained with sklearn v{stored_version}, current v{current_version}")
49
+ print(" Run 'python manage.py detect_and_train' to update model if needed.")
50
+
51
+ return model
52
+ else:
53
+ # Old format - direct model object
54
+ print("ℹ️ Using legacy model format. Consider retraining for better compatibility.")
55
+ return model_data
56
+
57
+ except Exception as e:
58
+ print(f"Warning: Could not load AI model from {MODEL_PATH}: {e}")
59
+ print("AI anomaly detection will be disabled until model is retrained.")
60
+ print("Run 'python manage.py detect_and_train' to regenerate the model.")
61
+ return None
62
+
63
+ # Load model with safety checks
64
+ MODEL = load_model_safely()
29
65
 
30
66
  STATIC_KW = getattr(
31
67
  settings,
@@ -130,8 +166,8 @@ class AIAnomalyMiddleware(MiddlewareMixin):
130
166
 
131
167
  def __init__(self, get_response=None):
132
168
  super().__init__(get_response)
133
- model_path = os.path.join(os.path.dirname(__file__), "resources", "model.pkl")
134
- self.model = joblib.load(model_path)
169
+ # Use the safely loaded global MODEL instead of loading again
170
+ self.model = MODEL
135
171
 
136
172
  def process_request(self, request):
137
173
  if is_exempt(request):
@@ -164,7 +200,9 @@ class AIAnomalyMiddleware(MiddlewareMixin):
164
200
  total_404 = sum(1 for (_, _, st, _) in data if st == 404)
165
201
  feats = [path_len, kw_hits, resp_time, status_idx, burst_count, total_404]
166
202
  X = np.array(feats, dtype=float).reshape(1, -1)
167
- if self.model.predict(X)[0] == -1:
203
+
204
+ # Only use AI model if it's available
205
+ if self.model is not None and self.model.predict(X)[0] == -1:
168
206
  if not is_ip_exempted(ip):
169
207
  BlacklistManager.block(ip, "AI anomaly")
170
208
  return JsonResponse({"error": "blocked"}, status=403)
@@ -17,7 +17,7 @@ from .utils import is_exempt_path
17
17
  from .storage import get_blacklist_store, get_exemption_store, get_keyword_store
18
18
 
19
19
  # ─────────── Configuration ───────────
20
- LOG_PATH = settings.AIWAF_ACCESS_LOG
20
+ LOG_PATH = getattr(settings, 'AIWAF_ACCESS_LOG', None)
21
21
  MODEL_PATH = os.path.join(os.path.dirname(__file__), "resources", "model.pkl")
22
22
 
23
23
  STATIC_KW = [".php", "xmlrpc", "wp-", ".env", ".git", ".bak", "conflg", "shell", "filemanager"]
@@ -192,11 +192,28 @@ def train() -> None:
192
192
  contamination=getattr(settings, "AIWAF_AI_CONTAMINATION", 0.05),
193
193
  random_state=42
194
194
  )
195
- model.fit(X)
195
+
196
+ # Suppress sklearn warnings during training
197
+ import warnings
198
+ with warnings.catch_warnings():
199
+ warnings.filterwarnings("ignore", category=UserWarning, module="sklearn")
200
+ model.fit(X)
196
201
 
197
202
  os.makedirs(os.path.dirname(MODEL_PATH), exist_ok=True)
198
- joblib.dump(model, MODEL_PATH)
199
- print(f"Model trained on {len(X)} samples → {MODEL_PATH}")
203
+
204
+ # Save model with version metadata
205
+ import sklearn
206
+ from django.utils import timezone as django_timezone
207
+ model_data = {
208
+ 'model': model,
209
+ 'sklearn_version': sklearn.__version__,
210
+ 'created_at': str(django_timezone.now()),
211
+ 'feature_count': len(feature_cols),
212
+ 'samples_count': len(X)
213
+ }
214
+ joblib.dump(model_data, MODEL_PATH)
215
+ print(f"✅ Model trained on {len(X)} samples → {MODEL_PATH}")
216
+ print(f"📦 Created with scikit-learn v{sklearn.__version__}")
200
217
 
201
218
  # Check for anomalies and intelligently decide which IPs to block
202
219
  preds = model.predict(X)
@@ -1,3 +1,24 @@
1
+ Metadata-Version: 2.4
2
+ Name: aiwaf
3
+ Version: 0.1.9.0.3
4
+ Summary: AI-powered Web Application Firewall
5
+ Home-page: https://github.com/aayushgauba/aiwaf
6
+ Author: Aayush Gauba
7
+ Author-email: Aayush Gauba <gauba.aayush@gmail.com>
8
+ License: MIT
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: Django>=3.2
13
+ Requires-Dist: numpy>=1.21
14
+ Requires-Dist: pandas>=1.3
15
+ Requires-Dist: scikit-learn<2.0,>=1.0
16
+ Requires-Dist: joblib>=1.1
17
+ Dynamic: author
18
+ Dynamic: home-page
19
+ Dynamic: license-file
20
+ Dynamic: requires-python
21
+
1
22
 
2
23
  # AI‑WAF
3
24
 
@@ -350,6 +371,7 @@ MIDDLEWARE = [
350
371
 
351
372
  **Common Issues:**
352
373
  - **AppRegistryNotReady Error**: Fixed in v0.1.9.0.1 - update with `pip install --upgrade aiwaf`
374
+ - **Scikit-learn Version Warnings**: Fixed in v0.1.9.0.3 - regenerate model with `python manage.py regenerate_model`
353
375
  - Missing Django: `pip install Django`
354
376
  - Old AI-WAF version: `pip install --upgrade aiwaf`
355
377
  - Missing migrations: `python manage.py migrate`
@@ -367,6 +389,24 @@ python manage.py detect_and_train
367
389
  1. Read access logs (incl. rotated or gzipped) **OR** AI-WAF middleware CSV logs
368
390
  2. Auto‑block IPs with ≥ 6 total 404s
369
391
  3. Extract features & train IsolationForest
392
+ 4. Save `model.pkl` with current scikit-learn version
393
+
394
+ ### Model Regeneration
395
+
396
+ If you see scikit-learn version warnings, regenerate the model:
397
+
398
+ ```bash
399
+ # Quick model regeneration (recommended)
400
+ python manage.py regenerate_model
401
+
402
+ # Full retraining with fresh data
403
+ python manage.py detect_and_train
404
+ ```
405
+
406
+ **Benefits:**
407
+ - ✅ Eliminates version compatibility warnings
408
+ - ✅ Uses current scikit-learn optimizations
409
+ - ✅ Maintains same protection level
370
410
  4. Save `model.pkl`
371
411
  5. Extract top 10 dynamic keywords from 4xx/5xx
372
412
  6. Remove any keywords associated with newly exempt paths
@@ -24,6 +24,7 @@ aiwaf/management/commands/aiwaf_diagnose.py
24
24
  aiwaf/management/commands/aiwaf_logging.py
25
25
  aiwaf/management/commands/aiwaf_reset.py
26
26
  aiwaf/management/commands/detect_and_train.py
27
+ aiwaf/management/commands/regenerate_model.py
27
28
  aiwaf/resources/model.pkl
28
29
  aiwaf/templatetags/__init__.py
29
30
  aiwaf/templatetags/aiwaf_tags.py
@@ -1,5 +1,5 @@
1
1
  Django>=3.2
2
2
  numpy>=1.21
3
3
  pandas>=1.3
4
- scikit-learn>=1.0
4
+ scikit-learn<2.0,>=1.0
5
5
  joblib>=1.1
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aiwaf"
3
- version = "0.1.9.0.1"
3
+ version = "0.1.9.0.3"
4
4
  description = "AI-powered Web Application Firewall"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.8"
@@ -10,6 +10,6 @@ dependencies = [
10
10
  "Django>=3.2",
11
11
  "numpy>=1.21",
12
12
  "pandas>=1.3",
13
- "scikit-learn>=1.0",
13
+ "scikit-learn>=1.0,<2.0",
14
14
  "joblib>=1.1"
15
15
  ]
@@ -9,7 +9,7 @@ long_description = (HERE / "README.md").read_text(encoding="utf-8")
9
9
 
10
10
  setup(
11
11
  name="aiwaf",
12
- version="0.1.9.0.1",
12
+ version="0.1.9.0.3",
13
13
  description="AI‑driven, self‑learning Web Application Firewall for Django",
14
14
  long_description=long_description,
15
15
  long_description_content_type="text/markdown",
@@ -22,7 +22,7 @@ setup(
22
22
  "Django>=3.2",
23
23
  "numpy>=1.21",
24
24
  "pandas>=1.3",
25
- "scikit-learn>=1.0",
25
+ "scikit-learn>=1.0,<2.0",
26
26
  "joblib>=1.1",
27
27
  ],
28
28
  include_package_data=True,
@@ -1,24 +0,0 @@
1
- default_app_config = "aiwaf.apps.AiwafConfig"
2
-
3
- __version__ = "0.1.9.0.1"
4
-
5
- # Note: Middleware classes are available from aiwaf.middleware
6
- # Import them only when needed to avoid circular imports during Django app loading= "aiwaf.apps.AiwafConfig"
7
-
8
- __version__ = "0.1.9.0.1"
9
-
10
- # Import main middleware classes for easier access
11
- try:
12
- from .middleware import (
13
- IPAndKeywordBlockMiddleware,
14
- RateLimitMiddleware,
15
- AIAnomalyMiddleware,
16
- HoneypotTimingMiddleware,
17
- UUIDTamperMiddleware
18
- )
19
- except ImportError as e:
20
- # Handle import errors gracefully during package installation
21
- import sys
22
- if 'runserver' in sys.argv or 'migrate' in sys.argv or 'shell' in sys.argv:
23
- print(f"Warning: Could not import middleware classes: {e}")
24
- print("Tip: Run 'python manage.py aiwaf_diagnose' to troubleshoot")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes