aiwaf 0.1.9.1.5__tar.gz → 0.1.9.1.7__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.
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/PKG-INFO +7 -1
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/README.md +6 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/__init__.py +1 -1
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/check_dependencies.py +17 -1
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/middleware.py +60 -9
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf.egg-info/PKG-INFO +7 -1
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/pyproject.toml +1 -1
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/setup.py +1 -1
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/LICENSE +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/apps.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/blacklist_manager.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/decorators.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/__init__.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/__init__.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/add_exemption.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/add_ipexemption.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/aiwaf_diagnose.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/aiwaf_logging.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/aiwaf_reset.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/clear_cache.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/debug_csv.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/detect_and_train.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/diagnose_blocking.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/regenerate_model.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/setup_models.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/test_exemption.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/management/commands/test_exemption_fix.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/middleware_logger.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/models.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/resources/model.pkl +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/storage.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/templatetags/__init__.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/templatetags/aiwaf_tags.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/trainer.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf/utils.py +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf.egg-info/SOURCES.txt +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf.egg-info/dependency_links.txt +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf.egg-info/requires.txt +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/aiwaf.egg-info/top_level.txt +0 -0
- {aiwaf-0.1.9.1.5 → aiwaf-0.1.9.1.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiwaf
|
|
3
|
-
Version: 0.1.9.1.
|
|
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
|
|
|
@@ -226,6 +226,7 @@ python manage.py check_dependencies --upgrade --check-security --update-requirem
|
|
|
226
226
|
- ✅ **Dry run mode** for testing upgrade plans
|
|
227
227
|
- ✅ **AIWAF compatibility validation**
|
|
228
228
|
- ✅ **Automatic requirements.txt updates** after successful upgrades
|
|
229
|
+
- ✅ **Pip cache clearing** to prevent cache-related issues
|
|
229
230
|
|
|
230
231
|
**Safe Upgrade System:**
|
|
231
232
|
|
|
@@ -282,6 +283,9 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
282
283
|
|
|
283
284
|
🎉 Upgrade complete: 2/2 packages upgraded successfully
|
|
284
285
|
|
|
286
|
+
🧹 Clearing pip cache...
|
|
287
|
+
✅ Pip cache cleared successfully
|
|
288
|
+
|
|
285
289
|
📝 Updating requirements.txt...
|
|
286
290
|
📋 Backup created: requirements.txt.backup
|
|
287
291
|
📦 pandas: pandas>=1.3 → pandas>=1.5.3
|
|
@@ -300,6 +304,7 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
300
304
|
- 🧪 **Dry Run Mode**: Test upgrade plans before execution
|
|
301
305
|
- ⚠️ **Clear Blocking Reasons**: Explains why upgrades are blocked
|
|
302
306
|
- 📝 **Requirements.txt Updates**: Automatically updates dependency files
|
|
307
|
+
- 🧹 **Cache Management**: Clears pip cache after successful upgrades
|
|
303
308
|
|
|
304
309
|
**Recommended Upgrade Workflow:**
|
|
305
310
|
|
|
@@ -338,6 +343,7 @@ The system uses a multi-layer decision process:
|
|
|
338
343
|
- **Layer 3**: Analyze cross-package dependencies
|
|
339
344
|
- **Layer 4**: Select highest safe version within constraints
|
|
340
345
|
- **Layer 5**: Execute with error handling and rollback capability
|
|
346
|
+
- **Layer 6**: Clear pip cache and update requirements.txt after success
|
|
341
347
|
|
|
342
348
|
This will ensure the IP is never blocked by AI‑WAF. You can also manage exemptions via the Django admin interface.
|
|
343
349
|
|
|
@@ -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"
|
|
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")
|
|
@@ -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
|
-
|
|
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
|
-
#
|
|
210
|
-
|
|
211
|
-
#
|
|
212
|
-
if
|
|
213
|
-
|
|
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.
|
|
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
|
|
|
@@ -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.1.
|
|
12
|
+
version="0.1.9.1.7",
|
|
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",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|