aiwaf 0.1.9.1.5__py3-none-any.whl → 0.1.9.1.7__py3-none-any.whl

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.

aiwaf/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  default_app_config = "aiwaf.apps.AiwafConfig"
2
2
 
3
- __version__ = "0.1.9.1.5"
3
+ __version__ = "0.1.9.1.7"
4
4
 
5
5
  # Note: Middleware classes are available from aiwaf.middleware
6
6
  # Import them only when needed to avoid circular imports during Django app loading
@@ -498,7 +498,9 @@ class Command(BaseCommand):
498
498
  else u['package']['name']
499
499
  for u in safe_upgrades
500
500
  ])
501
- self.stdout.write(f"Command that would be executed:\n {upgrade_cmd}")
501
+ self.stdout.write(f"Commands that would be executed:")
502
+ self.stdout.write(f" {upgrade_cmd}")
503
+ self.stdout.write(f" pip cache purge # Clear pip cache after upgrades")
502
504
  return []
503
505
  return []
504
506
  else:
@@ -537,6 +539,20 @@ class Command(BaseCommand):
537
539
  self.stdout.write(f"\n🎉 Upgrade complete: {success_count}/{len(safe_upgrades)} packages upgraded successfully")
538
540
 
539
541
  if success_count > 0:
542
+ # Clear pip cache after successful upgrades
543
+ self.stdout.write(self.style.HTTP_INFO("\n🧹 Clearing pip cache..."))
544
+ try:
545
+ cache_result = subprocess.run(['pip', 'cache', 'purge'],
546
+ capture_output=True, text=True, timeout=60)
547
+ if cache_result.returncode == 0:
548
+ self.stdout.write(self.style.SUCCESS(" ✅ Pip cache cleared successfully"))
549
+ else:
550
+ self.stdout.write(self.style.WARNING(f" ⚠️ Cache clear warning: {cache_result.stderr}"))
551
+ except subprocess.TimeoutExpired:
552
+ self.stdout.write(self.style.WARNING(" ⚠️ Pip cache clear timed out"))
553
+ except Exception as e:
554
+ self.stdout.write(self.style.WARNING(f" ⚠️ Could not clear pip cache: {e}"))
555
+
540
556
  self.stdout.write(self.style.HTTP_INFO("\n💡 Recommendations after upgrade:"))
541
557
  self.stdout.write(" 1. Run tests to ensure everything works correctly")
542
558
  self.stdout.write(" 2. Run 'python manage.py check_dependencies' again to verify")
aiwaf/middleware.py CHANGED
@@ -17,7 +17,7 @@ from django.urls import get_resolver
17
17
  from .trainer import STATIC_KW, STATUS_IDX, path_exists_in_django
18
18
  from .blacklist_manager import BlacklistManager
19
19
  from .models import IPExemption
20
- from .utils import is_exempt, get_ip, is_ip_exempted
20
+ from .utils import is_exempt, get_ip, is_ip_exempted, is_exempt_path
21
21
  from .storage import get_keyword_store
22
22
 
23
23
  MODEL_PATH = getattr(
@@ -191,10 +191,12 @@ class AIAnomalyMiddleware(MiddlewareMixin):
191
191
  key = f"aiwaf:{ip}"
192
192
  data = cache.get(key, [])
193
193
  path_len = len(request.path)
194
- if not path_exists_in_django(request.path) and not is_exempt(request):
194
+
195
+ # Use the same scoring logic as trainer.py
196
+ known_path = path_exists_in_django(request.path)
197
+ kw_hits = 0
198
+ if not known_path and not is_exempt_path(request.path):
195
199
  kw_hits = sum(1 for kw in STATIC_KW if kw in request.path.lower())
196
- else:
197
- kw_hits = 0
198
200
 
199
201
  resp_time = now - getattr(request, "_start_time", now)
200
202
  status_code = str(response.status_code)
@@ -206,11 +208,60 @@ class AIAnomalyMiddleware(MiddlewareMixin):
206
208
 
207
209
  # Only use AI model if it's available
208
210
  if self.model is not None and self.model.predict(X)[0] == -1:
209
- # BlacklistManager.block() now checks exemptions internally
210
- BlacklistManager.block(ip, "AI anomaly")
211
- # Check if actually blocked (exempted IPs won't be blocked)
212
- if BlacklistManager.is_blocked(ip):
213
- return JsonResponse({"error": "blocked"}, status=403)
211
+ # AI detected anomaly - but analyze patterns before blocking (like trainer.py)
212
+
213
+ # Get recent behavior data for this IP to make intelligent blocking decision
214
+ recent_data = [d for d in data if now - d[0] <= 300] # Last 5 minutes
215
+
216
+ if recent_data:
217
+ # Calculate behavior metrics similar to trainer.py
218
+ recent_kw_hits = []
219
+ recent_404s = 0
220
+ recent_burst_counts = []
221
+
222
+ for entry_time, entry_path, entry_status, entry_resp_time in recent_data:
223
+ # Calculate keyword hits for this entry
224
+ entry_known_path = path_exists_in_django(entry_path)
225
+ entry_kw_hits = 0
226
+ if not entry_known_path and not is_exempt_path(entry_path):
227
+ entry_kw_hits = sum(1 for kw in STATIC_KW if kw in entry_path.lower())
228
+ recent_kw_hits.append(entry_kw_hits)
229
+
230
+ # Count 404s
231
+ if entry_status == 404:
232
+ recent_404s += 1
233
+
234
+ # Calculate burst for this entry (requests within 10 seconds)
235
+ entry_burst = sum(1 for (t, _, _, _) in recent_data if abs(entry_time - t) <= 10)
236
+ recent_burst_counts.append(entry_burst)
237
+
238
+ # Calculate averages and maximums
239
+ avg_kw_hits = sum(recent_kw_hits) / len(recent_kw_hits) if recent_kw_hits else 0
240
+ max_404s = recent_404s
241
+ avg_burst = sum(recent_burst_counts) / len(recent_burst_counts) if recent_burst_counts else 0
242
+ total_requests = len(recent_data)
243
+
244
+ # Don't block if it looks like legitimate behavior (same thresholds as trainer.py):
245
+ if (
246
+ avg_kw_hits < 2 and # Not hitting many malicious keywords
247
+ max_404s < 10 and # Not excessive 404s
248
+ avg_burst < 15 and # Not excessive burst activity
249
+ total_requests < 100 # Not excessive total requests
250
+ ):
251
+ # Anomalous but looks legitimate - don't block
252
+ pass
253
+ else:
254
+ # Block if it shows clear signs of malicious behavior
255
+ BlacklistManager.block(ip, f"AI anomaly + suspicious patterns (kw:{avg_kw_hits:.1f}, 404s:{max_404s}, burst:{avg_burst:.1f})")
256
+ # Check if actually blocked (exempted IPs won't be blocked)
257
+ if BlacklistManager.is_blocked(ip):
258
+ return JsonResponse({"error": "blocked"}, status=403)
259
+ else:
260
+ # No recent data to analyze - be more conservative, only block on very suspicious current request
261
+ if kw_hits >= 2 or status_idx == STATUS_IDX.index("404"):
262
+ BlacklistManager.block(ip, "AI anomaly + immediate suspicious behavior")
263
+ if BlacklistManager.is_blocked(ip):
264
+ return JsonResponse({"error": "blocked"}, status=403)
214
265
 
215
266
  data.append((now, request.path, response.status_code, resp_time))
216
267
  data = [d for d in data if now - d[0] < self.WINDOW]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.9.1.5
3
+ Version: 0.1.9.1.7
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -249,6 +249,7 @@ python manage.py check_dependencies --upgrade --check-security --update-requirem
249
249
  - ✅ **Dry run mode** for testing upgrade plans
250
250
  - ✅ **AIWAF compatibility validation**
251
251
  - ✅ **Automatic requirements.txt updates** after successful upgrades
252
+ - ✅ **Pip cache clearing** to prevent cache-related issues
252
253
 
253
254
  **Safe Upgrade System:**
254
255
 
@@ -305,6 +306,9 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
305
306
 
306
307
  🎉 Upgrade complete: 2/2 packages upgraded successfully
307
308
 
309
+ 🧹 Clearing pip cache...
310
+ ✅ Pip cache cleared successfully
311
+
308
312
  📝 Updating requirements.txt...
309
313
  📋 Backup created: requirements.txt.backup
310
314
  📦 pandas: pandas>=1.3 → pandas>=1.5.3
@@ -323,6 +327,7 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
323
327
  - 🧪 **Dry Run Mode**: Test upgrade plans before execution
324
328
  - ⚠️ **Clear Blocking Reasons**: Explains why upgrades are blocked
325
329
  - 📝 **Requirements.txt Updates**: Automatically updates dependency files
330
+ - 🧹 **Cache Management**: Clears pip cache after successful upgrades
326
331
 
327
332
  **Recommended Upgrade Workflow:**
328
333
 
@@ -361,6 +366,7 @@ The system uses a multi-layer decision process:
361
366
  - **Layer 3**: Analyze cross-package dependencies
362
367
  - **Layer 4**: Select highest safe version within constraints
363
368
  - **Layer 5**: Execute with error handling and rollback capability
369
+ - **Layer 6**: Clear pip cache and update requirements.txt after success
364
370
 
365
371
  This will ensure the IP is never blocked by AI‑WAF. You can also manage exemptions via the Django admin interface.
366
372
 
@@ -1,8 +1,8 @@
1
- aiwaf/__init__.py,sha256=XpqePdxlyW-5RJkAUTNtlGeSUYFl7vaRQ6JrnHU1W-Y,220
1
+ aiwaf/__init__.py,sha256=hhKVupfj0NOn_nRM1Ukd6aUP9mL5OkjKLE-tZ3xGdIE,220
2
2
  aiwaf/apps.py,sha256=nCez-Ptlv2kaEk5HenA8b1pATz1VfhrHP1344gwcY1A,142
3
3
  aiwaf/blacklist_manager.py,sha256=LYCeKFB-7e_C6Bg2WeFJWFIIQlrfRMPuGp30ivrnhQY,1196
4
4
  aiwaf/decorators.py,sha256=IUKOdM_gdroffImRZep1g1wT6gNqD10zGwcp28hsJCs,825
5
- aiwaf/middleware.py,sha256=4Ox0pUdB7rMT1Sw5XHO6-udQrfqyF9VGdkkkgLioRJ0,12470
5
+ aiwaf/middleware.py,sha256=EMAQA_Gnz0jv4nevlognT921ZeBEro13J_DSv_mQ3Dw,15482
6
6
  aiwaf/middleware_logger.py,sha256=LWZVDAnjh6CGESirA8eMbhGgJKB7lVDGRQqVroH95Lo,4742
7
7
  aiwaf/models.py,sha256=vQxgY19BDVMjoO903UNrTZC1pNoLltMU6wbyWPoAEns,2719
8
8
  aiwaf/storage.py,sha256=HYSnis7S8ETsos_NxWkd05OoiHXMhIWQy8FcFTqO4vk,8408
@@ -15,7 +15,7 @@ aiwaf/management/commands/add_ipexemption.py,sha256=sSf3d9hGK9RqqlBYkCrnrd8KZWGT
15
15
  aiwaf/management/commands/aiwaf_diagnose.py,sha256=nXFRhq66N4QC3e4scYJ2sUngJce-0yDxtBO3R2BllRM,6134
16
16
  aiwaf/management/commands/aiwaf_logging.py,sha256=FCIqULn2tii2vD9VxL7vk3PV4k4vr7kaA00KyaCExYY,7692
17
17
  aiwaf/management/commands/aiwaf_reset.py,sha256=0FIBqpZS8xgFFvAKJ-0zAC_-QNQwRkOHpXb8N-OdFr8,3740
18
- aiwaf/management/commands/check_dependencies.py,sha256=pxON6cFrBTWtNRzPOzB_S4Jdld1G6q1O_ds3xtbjq8Y,36134
18
+ aiwaf/management/commands/check_dependencies.py,sha256=GOZl00pDwW2cJjDvIaCeB3yWxmeYcJDRTIpmOTLvy2c,37204
19
19
  aiwaf/management/commands/clear_cache.py,sha256=cdnuTgxkhKLqT_6k6yTcEBlREovNRQxAE51ceXlGYMA,647
20
20
  aiwaf/management/commands/debug_csv.py,sha256=Lddqp37mIn0zdvHf4GbuNTWYyJ5h8bumDcGmFSAioi0,6801
21
21
  aiwaf/management/commands/detect_and_train.py,sha256=-o-LZ7QZ5GeJPCekryox1DGXKMmFEkwwrcDsiM166K0,269
@@ -27,8 +27,8 @@ aiwaf/management/commands/test_exemption_fix.py,sha256=ngyGaHUCmQQ6y--6j4q1viZJt
27
27
  aiwaf/resources/model.pkl,sha256=5t6h9BX8yoh2xct85MXOO60jdlWyg1APskUOW0jZE1Y,1288265
28
28
  aiwaf/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  aiwaf/templatetags/aiwaf_tags.py,sha256=XXfb7Tl4DjU3Sc40GbqdaqOEtKTUKELBEk58u83wBNw,357
30
- aiwaf-0.1.9.1.5.dist-info/licenses/LICENSE,sha256=Ir8PX4dxgAcdB0wqNPIkw84fzIIRKE75NoUil9RX0QU,1069
31
- aiwaf-0.1.9.1.5.dist-info/METADATA,sha256=7hXUI5PEFAGOTugMBbECEz1SgMHbb8NEnYt_Alg4yFM,21873
32
- aiwaf-0.1.9.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- aiwaf-0.1.9.1.5.dist-info/top_level.txt,sha256=kU6EyjobT6UPCxuWpI_BvcHDG0I2tMgKaPlWzVxe2xI,6
34
- aiwaf-0.1.9.1.5.dist-info/RECORD,,
30
+ aiwaf-0.1.9.1.7.dist-info/licenses/LICENSE,sha256=Ir8PX4dxgAcdB0wqNPIkw84fzIIRKE75NoUil9RX0QU,1069
31
+ aiwaf-0.1.9.1.7.dist-info/METADATA,sha256=P3lYeDWOKfjHCBWcaEoFpN5lJJkj0iP_HWIJjAI-hz0,22145
32
+ aiwaf-0.1.9.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
+ aiwaf-0.1.9.1.7.dist-info/top_level.txt,sha256=kU6EyjobT6UPCxuWpI_BvcHDG0I2tMgKaPlWzVxe2xI,6
34
+ aiwaf-0.1.9.1.7.dist-info/RECORD,,