aiwaf 0.1.7.3__tar.gz → 0.1.7.6__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 (24) hide show
  1. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/PKG-INFO +1 -1
  2. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/middleware.py +31 -24
  3. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf.egg-info/PKG-INFO +1 -1
  4. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/pyproject.toml +1 -1
  5. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/setup.py +1 -1
  6. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/LICENSE +0 -0
  7. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/README.md +0 -0
  8. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/__init__.py +0 -0
  9. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/apps.py +0 -0
  10. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/blacklist_manager.py +0 -0
  11. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/management/__init__.py +0 -0
  12. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/management/commands/__init__.py +0 -0
  13. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/management/commands/detect_and_train.py +0 -0
  14. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/models.py +0 -0
  15. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/resources/model.pkl +0 -0
  16. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/storage.py +0 -0
  17. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/templatetags/__init__.py +0 -0
  18. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/templatetags/aiwaf_tags.py +0 -0
  19. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/trainer.py +0 -0
  20. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf/utils.py +0 -0
  21. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf.egg-info/SOURCES.txt +0 -0
  22. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf.egg-info/dependency_links.txt +0 -0
  23. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/aiwaf.egg-info/top_level.txt +0 -0
  24. {aiwaf-0.1.7.3 → aiwaf-0.1.7.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.7.3
3
+ Version: 0.1.7.6
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -14,7 +14,7 @@ from django.core.cache import cache
14
14
  from django.db.models import F
15
15
  from django.apps import apps
16
16
  from django.urls import get_resolver
17
-
17
+ from .trainer import STATIC_KW, STATUS_IDX, is_exempt_path, path_exists_in_django
18
18
  from .blacklist_manager import BlacklistManager
19
19
  from .models import DynamicKeyword
20
20
 
@@ -131,17 +131,45 @@ class AIAnomalyMiddleware(MiddlewareMixin):
131
131
  WINDOW = getattr(settings, "AIWAF_WINDOW_SECONDS", 60)
132
132
  TOP_N = getattr(settings, "AIWAF_DYNAMIC_TOP_N", 10)
133
133
 
134
+ def __init__(self, get_response=None):
135
+ super().__init__(get_response)
136
+ model_path = os.path.join(os.path.dirname(__file__), "resources", "model.pkl")
137
+ self.model = joblib.load(model_path)
138
+
134
139
  def process_request(self, request):
135
140
  if is_exempt_path(request.path):
136
141
  return None
142
+ request._start_time = time.time()
137
143
  ip = get_ip(request)
138
144
  if BlacklistManager.is_blocked(ip):
139
145
  return JsonResponse({"error": "blocked"}, status=403)
146
+ return None
140
147
 
148
+ def process_response(self, request, response):
149
+ if is_exempt_path(request.path):
150
+ return response
151
+ ip = get_ip(request)
141
152
  now = time.time()
142
153
  key = f"aiwaf:{ip}"
143
154
  data = cache.get(key, [])
144
- data.append((now, request.path, 0, 0.0))
155
+ path_len = len(request.path)
156
+ if not path_exists_in_django(request.path) and not is_exempt_path(request.path):
157
+ kw_hits = sum(1 for kw in STATIC_KW if kw in request.path.lower())
158
+ else:
159
+ kw_hits = 0
160
+
161
+ resp_time = now - getattr(request, "_start_time", now)
162
+ status_code = str(response.status_code)
163
+ status_idx = STATUS_IDX.index(status_code) if status_code in STATUS_IDX else -1
164
+ burst_count = sum(1 for (t, _, _, _) in data if now - t <= 10)
165
+ total_404 = sum(1 for (_, _, st, _) in data if st == 404)
166
+ feats = [path_len, kw_hits, resp_time, status_idx, burst_count, total_404]
167
+ X = np.array(feats, dtype=float).reshape(1, -1)
168
+ if self.model.predict(X)[0] == -1:
169
+ BlacklistManager.block(ip, "AI anomaly")
170
+ return JsonResponse({"error": "blocked"}, status=403)
171
+
172
+ data.append((now, request.path, response.status_code, resp_time))
145
173
  data = [d for d in data if now - d[0] < self.WINDOW]
146
174
  cache.set(key, data, timeout=self.WINDOW)
147
175
  for seg in re.split(r"\W+", request.path.lower()):
@@ -149,28 +177,7 @@ class AIAnomalyMiddleware(MiddlewareMixin):
149
177
  obj, _ = DynamicKeyword.objects.get_or_create(keyword=seg)
150
178
  DynamicKeyword.objects.filter(pk=obj.pk).update(count=F("count") + 1)
151
179
 
152
- if len(data) < 5:
153
- return None
154
- top_dynamic = list(
155
- DynamicKeyword.objects
156
- .order_by("-count")
157
- .values_list("keyword", flat=True)[: self.TOP_N]
158
- )
159
- ALL_KW = set(STATIC_KW) | set(top_dynamic)
160
-
161
- total = len(data)
162
- ratio404 = sum(1 for (_, _, st, _) in data if st == 404) / total
163
- hits = sum(any(kw in path.lower() for kw in ALL_KW) for (_, path, _, _) in data)
164
- avg_rt = np.mean([rt for (_, _, _, rt) in data]) if data else 0.0
165
- ivs = [data[i][0] - data[i - 1][0] for i in range(1, total)]
166
- avg_iv = np.mean(ivs) if ivs else 0.0
167
-
168
- X = np.array([[total, ratio404, hits, avg_rt, avg_iv]], dtype=float)
169
- if MODEL.predict(X)[0] == -1:
170
- BlacklistManager.block(ip, "AI anomaly")
171
- return JsonResponse({"error": "blocked"}, status=403)
172
-
173
- return None
180
+ return response
174
181
 
175
182
 
176
183
  class HoneypotMiddleware(MiddlewareMixin):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.7.3
3
+ Version: 0.1.7.6
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aiwaf"
3
- version = "0.1.7.3"
3
+ version = "0.1.7.6"
4
4
  description = "AI-powered Web Application Firewall"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.8"
@@ -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.7.3",
12
+ version="0.1.7.6",
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