From 22c9f66dcfaf109957b12c9dfb62c8973f8c294d Mon Sep 17 00:00:00 2001 From: surya Date: Sat, 4 Jul 2026 21:36:03 +0530 Subject: [PATCH 01/11] [feat]: add XXE_INJECTION regex pattern to ATTACK_COMBINED --- .../backend/app/core/features/patterns.py | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py b/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py index dea8763c..9b02a650 100644 --- a/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py +++ b/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py @@ -3,7 +3,7 @@ patterns.py Compiled regex patterns for web attack detection covering -9 OWASP categories plus encoding anomalies +10 OWASP categories plus encoding anomalies Defines case-insensitive compiled patterns for: SQLI (union select, sleep, benchmark, information_schema, hex @@ -14,13 +14,16 @@ document.cookie/write, eval/alert/prompt), PATH_TRAVERSAL etc/passwd, .git/config, .env), COMMAND_INJECTION (semicolon/pipe chaining to shell commands, $() and backtick substitution, ${} expansion), FILE_INCLUSION -(php://, file://, data://, phar:// wrapper schemes), SSRF -(cloud metadata IPs 169.254.169.254, localhost with paths, -dict:// and gopher://), LOG4SHELL (${jndi, ${lower, ${:- -patterns), CRLF_INJECTION (%0d%0a sequences, bare CR/LF), +(php://, file://, data://, phar:// wrapper schemes), +XXE_INJECTION ( Date: Sat, 4 Jul 2026 21:36:08 +0530 Subject: [PATCH 02/11] [feat]: register XXE_INJECTION detection rule with score 0.82 --- .../backend/app/core/detection/rules.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py b/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py index 41a65844..8d2ae22a 100644 --- a/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py +++ b/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py @@ -5,11 +5,11 @@ rules.py Cold-start rule-based detection engine inspired by ModSecurity Core Rule Set -RuleEngine.score_request evaluates requests against 9 +RuleEngine.score_request evaluates requests against 10 regex-based _PatternRules (LOG4SHELL 0.95, COMMAND_ INJECTION 0.90, SQL_INJECTION 0.85, XSS 0.80, FILE_ -INCLUSION 0.75, SSRF 0.70, CRLF_INJECTION 0.65, -PATH_TRAVERSAL 0.60, OPEN_REDIRECT 0.55), +INCLUSION 0.75, XXE_INJECTION 0.82, SSRF 0.70, CRLF_ +INJECTION 0.65, PATH_TRAVERSAL 0.60, OPEN_REDIRECT 0.55), double-encoding detection (0.40), scanner user-agent signature matching (0.35), and 2 _ThresholdRules (RATE_ANOMALY >100 req/min 0.30, HIGH_ERROR_RATE >50% @@ -46,6 +46,7 @@ from app.core.features.patterns import ( SQLI, SSRF, XSS, + XXE_INJECTION, ) from app.core.features.signatures import SCANNER_USER_AGENTS from app.core.detection.ensemble import classify_severity as _classify_severity @@ -78,6 +79,7 @@ _PATTERN_RULES: list[_PatternRule] = [ _PatternRule("COMMAND_INJECTION", COMMAND_INJECTION, 0.90), _PatternRule("SQL_INJECTION", SQLI, 0.85), _PatternRule("XSS", XSS, 0.80), + _PatternRule("XXE_INJECTION", XXE_INJECTION, 0.82), _PatternRule("FILE_INCLUSION", FILE_INCLUSION, 0.75), _PatternRule("SSRF", SSRF, 0.70), _PatternRule("PATH_TRAVERSAL", PATH_TRAVERSAL, 0.60), From 614fc12bf2532729741102246d65b8c227e22ca8 Mon Sep 17 00:00:00 2001 From: surya Date: Sat, 4 Jul 2026 21:36:12 +0530 Subject: [PATCH 03/11] [feat]: add xxe simulation mode with 5 XXE payload variants --- .../ai-threat-detection/dev-log/simulate.py | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py b/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py index db011e32..afaaa8a0 100755 --- a/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py +++ b/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py @@ -6,16 +6,17 @@ simulate.py HTTP traffic simulator for generating realistic attack and normal log patterns against the dev-log target application -Provides 10 traffic modes via argparse: normal (benign +Provides 11 traffic modes via argparse: normal (benign browsing with GET/POST mix), sqli (12 SQL injection payloads), xss (10 script/event handler vectors), traversal (10 dot-dot-slash and encoding variants), cmdi (7 shell command injection payloads), log4shell (4 JNDI lookup variants), ssrf (5 cloud metadata and internal -service targets), scanner (20 recon paths with 11 scanner -user-agents), flood (rapid-fire requests), and mixed -(50/10/40 normal/scanner/attack split). Uses urllib for -HTTP requests with configurable count, delay, and target +service targets), xxe (5 XML external entity payloads), +scanner (20 recon paths with 11 scanner user-agents), +flood (rapid-fire requests), and mixed (50/10/40 +normal/scanner/attack split). Uses urllib for HTTP +requests with configurable count, delay, and target URL. Checks /health reachability before starting Connects to: @@ -29,6 +30,7 @@ import random import sys import time import urllib.error +import urllib.parse import urllib.request DEFAULT_TARGET = "http://localhost:58319" @@ -117,6 +119,19 @@ SSRF_PAYLOADS = [ "/api/search?url=http://metadata.google.internal/computeMetadata/v1/", ] +XXE_PAYLOADS = [ + # Classic file disclosure via internal entity + "/api/test?data=%3C!DOCTYPE+foo+%5B%3C!ENTITY+xxe+SYSTEM+%22file%3A%2F%2F%2Fetc%2Fpasswd%22%3E%5D%3E", + # SYSTEM keyword targeting /etc/hosts + "/api/test?xml=]>", + # XInclude (xmlns:xi) attempt + "/api/test?body=", + # URL-encoded ]>&q=&xxe;", +] + SCANNER_USER_AGENTS = [ "Nikto/2.1.6", "sqlmap/1.7.2#stable (https://sqlmap.org)", @@ -149,11 +164,13 @@ ATTACK_POOLS = { "cmdi": COMMAND_INJECTION_PAYLOADS, "log4shell": LOG4SHELL_PAYLOADS, "ssrf": SSRF_PAYLOADS, + "xxe": XXE_PAYLOADS, } def send(target, path, user_agent=None, method="GET"): - url = f"{target}{path}" + encoded_path = urllib.parse.quote(path, safe="/?&=") + url = f"{target}{encoded_path}" ua = user_agent or random.choice(NORMAL_USER_AGENTS) req = urllib.request.Request(url, headers={"User-Agent": ua}) if method == "POST": @@ -270,6 +287,7 @@ MODES = { "cmdi": lambda t, c, d: run_attack(t, c, d, "cmdi"), "log4shell": lambda t, c, d: run_attack(t, c, d, "log4shell"), "ssrf": lambda t, c, d: run_attack(t, c, d, "ssrf"), + "xxe": lambda t, c, d: run_attack(t, c, d, "xxe"), "scanner": lambda t, c, d: run_scanner(t, c, d), "flood": lambda t, c, d: run_flood(t, c, d), "mixed": lambda t, c, d: run_mixed(t, c, d), From 7f536cb617c21c2befef33fdac562b338aa67406 Mon Sep 17 00:00:00 2001 From: surya Date: Sat, 4 Jul 2026 21:36:16 +0530 Subject: [PATCH 04/11] [fix]: correct postgres volume mount path to /var/lib/postgresql --- PROJECTS/advanced/ai-threat-detection/compose.yml | 2 +- PROJECTS/advanced/ai-threat-detection/dev.compose.yml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/compose.yml b/PROJECTS/advanced/ai-threat-detection/compose.yml index 86a1d593..b7894d3e 100644 --- a/PROJECTS/advanced/ai-threat-detection/compose.yml +++ b/PROJECTS/advanced/ai-threat-detection/compose.yml @@ -26,7 +26,7 @@ services: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD required} POSTGRES_INITDB_ARGS: "-E UTF8 --locale=C" volumes: - - postgres_data:/var/lib/postgresql/data + - postgres_data:/var/lib/postgresql networks: - vigil_network healthcheck: diff --git a/PROJECTS/advanced/ai-threat-detection/dev.compose.yml b/PROJECTS/advanced/ai-threat-detection/dev.compose.yml index 3575a9aa..91aea42e 100644 --- a/PROJECTS/advanced/ai-threat-detection/dev.compose.yml +++ b/PROJECTS/advanced/ai-threat-detection/dev.compose.yml @@ -25,7 +25,7 @@ services: ports: - "${POSTGRES_HOST_PORT:-16969}:5432" volumes: - - postgres_dev:/var/lib/postgresql/data + - postgres_dev:/var/lib/postgresql networks: - vigil_dev healthcheck: @@ -72,6 +72,7 @@ services: ports: - "${BACKEND_HOST_PORT:-36969}:8000" volumes: + - ./backend:/app - model_data_dev:/app/data/models - nginx_logs_dev:/var/log/nginx depends_on: @@ -95,6 +96,7 @@ services: container_name: vigil-frontend-dev environment: VITE_API_TARGET: http://backend:8000 + CI: "true" ports: - "${FRONTEND_HOST_PORT:-46969}:5173" volumes: From ae159b3e7a52a9b073d13201932be62fada9371b Mon Sep 17 00:00:00 2001 From: surya Date: Sat, 4 Jul 2026 21:36:29 +0530 Subject: [PATCH 05/11] [chore]: copy lockfile and workspace config before pnpm install in Dockerfiles --- PROJECTS/advanced/ai-threat-detection/infra/docker/vite.dev | 2 +- PROJECTS/advanced/ai-threat-detection/infra/docker/vite.prod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.dev b/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.dev index 37b05c47..fc4e4233 100644 --- a/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.dev +++ b/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.dev @@ -16,7 +16,7 @@ RUN corepack enable && corepack prepare pnpm@latest --activate WORKDIR /app -COPY frontend/package.json ./ +COPY frontend/package.json frontend/pnpm-lock.yaml* frontend/pnpm-workspace.yaml* ./ RUN pnpm install COPY frontend/ . diff --git a/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.prod b/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.prod index 4be580cb..d3bf551b 100644 --- a/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.prod +++ b/PROJECTS/advanced/ai-threat-detection/infra/docker/vite.prod @@ -16,7 +16,7 @@ RUN corepack enable && corepack prepare pnpm@latest --activate WORKDIR /app -COPY frontend/package.json ./ +COPY frontend/package.json frontend/pnpm-lock.yaml* frontend/pnpm-workspace.yaml* ./ RUN pnpm install --frozen-lockfile COPY frontend/ . From b29476d1d84c5c0e0ed9b5b98d28286e62025759 Mon Sep 17 00:00:00 2001 From: surya Date: Sat, 4 Jul 2026 21:36:38 +0530 Subject: [PATCH 06/11] [chore]: bump rolldown-vite to 7.3.1 and migrate pnpm overrides to root --- .../ai-threat-detection/frontend/package.json | 9 +- .../frontend/pnpm-lock.yaml | 175 ++++++++---------- 2 files changed, 87 insertions(+), 97 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/frontend/package.json b/PROJECTS/advanced/ai-threat-detection/frontend/package.json index e7fc7284..16d2bfa4 100644 --- a/PROJECTS/advanced/ai-threat-detection/frontend/package.json +++ b/PROJECTS/advanced/ai-threat-detection/frontend/package.json @@ -42,9 +42,12 @@ "vite": "npm:rolldown-vite@7.3.1", "vite-tsconfig-paths": "^6.0.5" }, + "overrides": { + "vite": "npm:rolldown-vite@7.2.5" + }, "pnpm": { - "overrides": { - "vite": "npm:rolldown-vite@7.2.5" - } + "onlyBuiltDependencies": [ + "@parcel/watcher" + ] } } diff --git a/PROJECTS/advanced/ai-threat-detection/frontend/pnpm-lock.yaml b/PROJECTS/advanced/ai-threat-detection/frontend/pnpm-lock.yaml index a76043c9..5351cfd7 100644 --- a/PROJECTS/advanced/ai-threat-detection/frontend/pnpm-lock.yaml +++ b/PROJECTS/advanced/ai-threat-detection/frontend/pnpm-lock.yaml @@ -4,9 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - vite: npm:rolldown-vite@7.2.5 - importers: .: @@ -62,7 +59,7 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^5.1.2 - version: 5.1.4(rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3)) + version: 5.1.4(rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3)) sass: specifier: ^1.97.3 version: 1.97.3 @@ -79,11 +76,11 @@ importers: specifier: ~5.9.3 version: 5.9.3 vite: - specifier: npm:rolldown-vite@7.2.5 - version: rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3) + specifier: npm:rolldown-vite@7.3.1 + version: rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3) vite-tsconfig-paths: specifier: ^6.0.5 - version: 6.1.1(rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3))(typescript@5.9.3) + version: 6.1.1(rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3))(typescript@5.9.3) packages: @@ -321,12 +318,12 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxc-project/runtime@0.97.0': - resolution: {integrity: sha512-yH0zw7z+jEws4dZ4IUKoix5Lh3yhqIJWF9Dc8PWvhpo7U7O+lJrv7ZZL4BeRO0la8LBQFwcCewtLBnVV7hPe/w==} + '@oxc-project/runtime@0.101.0': + resolution: {integrity: sha512-t3qpfVZIqSiLQ5Kqt/MC4Ge/WCOGrrcagAdzTcDaggupjiGxUx4nJF2v6wUCXWSzWHn5Ns7XLv13fCJEwCOERQ==} engines: {node: ^20.19.0 || >=22.12.0} - '@oxc-project/types@0.97.0': - resolution: {integrity: sha512-lxmZK4xFrdvU0yZiDwgVQTCvh2gHWBJCBk5ALsrtsBWhs0uDIi+FTOnXRQeQfs304imdvTdaakT/lqwQ8hkOXQ==} + '@oxc-project/types@0.101.0': + resolution: {integrity: sha512-nuFhqlUzJX+gVIPPfuE6xurd4lST3mdcWOhyK/rZO0B9XWMKm79SuszIQEnSMmmDhq1DC8WWVYGVd+6F93o1gQ==} '@parcel/watcher-android-arm64@2.5.6': resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} @@ -416,95 +413,89 @@ packages: resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} engines: {node: '>= 10.0.0'} - '@rolldown/binding-android-arm64@1.0.0-beta.50': - resolution: {integrity: sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag==} + '@rolldown/binding-android-arm64@1.0.0-beta.53': + resolution: {integrity: sha512-Ok9V8o7o6YfSdTTYA/uHH30r3YtOxLD6G3wih/U9DO0ucBBFq8WPt/DslU53OgfteLRHITZny9N/qCUxMf9kjQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-beta.50': - resolution: {integrity: sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w==} + '@rolldown/binding-darwin-arm64@1.0.0-beta.53': + resolution: {integrity: sha512-yIsKqMz0CtRnVa6x3Pa+mzTihr4Ty+Z6HfPbZ7RVbk1Uxnco4+CUn7Qbm/5SBol1JD/7nvY8rphAgyAi7Lj6Vg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-beta.50': - resolution: {integrity: sha512-fFXDjXnuX7/gQZQm/1FoivVtRcyAzdjSik7Eo+9iwPQ9EgtA5/nB2+jmbzaKtMGG3q+BnZbdKHCtOacmNrkIDA==} + '@rolldown/binding-darwin-x64@1.0.0-beta.53': + resolution: {integrity: sha512-GTXe+mxsCGUnJOFMhfGWmefP7Q9TpYUseHvhAhr21nCTgdS8jPsvirb0tJwM3lN0/u/cg7bpFNa16fQrjKrCjQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-beta.50': - resolution: {integrity: sha512-F1b6vARy49tjmT/hbloplzgJS7GIvwWZqt+tAHEstCh0JIh9sa8FAMVqEmYxDviqKBaAI8iVvUREm/Kh/PD26Q==} + '@rolldown/binding-freebsd-x64@1.0.0-beta.53': + resolution: {integrity: sha512-9Tmp7bBvKqyDkMcL4e089pH3RsjD3SUungjmqWtyhNOxoQMh0fSmINTyYV8KXtE+JkxYMPWvnEt+/mfpVCkk8w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50': - resolution: {integrity: sha512-U6cR76N8T8M6lHj7EZrQ3xunLPxSvYYxA8vJsBKZiFZkT8YV4kjgCO3KwMJL0NOjQCPGKyiXO07U+KmJzdPGRw==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': + resolution: {integrity: sha512-a1y5fiB0iovuzdbjUxa7+Zcvgv+mTmlGGC4XydVIsyl48eoxgaYkA3l9079hyTyhECsPq+mbr0gVQsFU11OJAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50': - resolution: {integrity: sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': + resolution: {integrity: sha512-bpIGX+ov9PhJYV+wHNXl9rzq4F0QvILiURn0y0oepbQx+7stmQsKA0DhPGwmhfvF856wq+gbM8L92SAa/CBcLg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50': - resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==} + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': + resolution: {integrity: sha512-bGe5EBB8FVjHBR1mOLOPEFg1Lp3//7geqWkU5NIhxe+yH0W8FVrQ6WRYOap4SUTKdklD/dC4qPLREkMMQ855FA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50': - resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==} + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': + resolution: {integrity: sha512-qL+63WKVQs1CMvFedlPt0U9PiEKJOAL/bsHMKUDS6Vp2Q+YAv/QLPu8rcvkfIMvQ0FPU2WL0aX4eWwF6e/GAnA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-beta.50': - resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==} + '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': + resolution: {integrity: sha512-VGl9JIGjoJh3H8Mb+7xnVqODajBmrdOOb9lxWXdcmxyI+zjB2sux69br0hZJDTyLJfvBoYm439zPACYbCjGRmw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-beta.50': - resolution: {integrity: sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==} + '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': + resolution: {integrity: sha512-B4iIserJXuSnNzA5xBLFUIjTfhNy7d9sq4FUMQY3GhQWGVhS2RWWzzDnkSU6MUt7/aHUrep0CdQfXUJI9D3W7A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-beta.50': - resolution: {integrity: sha512-nmCN0nIdeUnmgeDXiQ+2HU6FT162o+rxnF7WMkBm4M5Ds8qTU7Dzv2Wrf22bo4ftnlrb2hKK6FSwAJSAe2FWLg==} + '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': + resolution: {integrity: sha512-BUjAEgpABEJXilGq/BPh7jeU3WAJ5o15c1ZEgHaDWSz3LB881LQZnbNJHmUiM4d1JQWMYYyR1Y490IBHi2FPJg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50': - resolution: {integrity: sha512-7kcNLi7Ua59JTTLvbe1dYb028QEPaJPJQHqkmSZ5q3tJueUeb6yjRtx8mw4uIqgWZcnQHAR3PrLN4XRJxvgIkA==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': + resolution: {integrity: sha512-s27uU7tpCWSjHBnxyVXHt3rMrQdJq5MHNv3BzsewCIroIw3DJFjMH1dzCPPMUFxnh1r52Nf9IJ/eWp6LDoyGcw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50': - resolution: {integrity: sha512-lL70VTNvSCdSZkDPPVMwWn/M2yQiYvSoXw9hTLgdIWdUfC3g72UaruezusR6ceRuwHCY1Ayu2LtKqXkBO5LIwg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ia32] - os: [win32] - - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50': - resolution: {integrity: sha512-4qU4x5DXWB4JPjyTne/wBNPqkbQU8J45bl21geERBKtEittleonioACBL1R0PsBu0Aq21SwMK5a9zdBkWSlQtQ==} + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': + resolution: {integrity: sha512-cjWL/USPJ1g0en2htb4ssMjIycc36RvdQAx1WlXnS6DpULswiUTVXPDesTifSKYSyvx24E0YqQkEm0K/M2Z/AA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-beta.50': - resolution: {integrity: sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==} + '@rolldown/pluginutils@1.0.0-beta.53': + resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} '@rolldown/pluginutils@1.0.0-rc.3': resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} @@ -1197,14 +1188,14 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rolldown-vite@7.2.5: - resolution: {integrity: sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA==} + rolldown-vite@7.3.1: + resolution: {integrity: sha512-LYzdNAjRHhF2yA4JUQm/QyARyi216N2rpJ0lJZb8E9FU2y5v6Vk+xq/U4XBOxMefpWixT5H3TslmAHm1rqIq2w==} engines: {node: ^20.19.0 || >=22.12.0} - deprecated: Use 7.3.1 for migration purposes. For the most recent updates, migrate to Vite 8 once you're ready. + deprecated: Use this package to migrate from Vite 7 to Vite 8. For the most recent updates, migrate to Vite 8 once you're ready. hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - esbuild: ^0.25.0 + esbuild: ^0.27.0 jiti: '>=1.21.0' less: ^4.0.0 sass: ^1.70.0 @@ -1238,8 +1229,8 @@ packages: yaml: optional: true - rolldown@1.0.0-beta.50: - resolution: {integrity: sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A==} + rolldown@1.0.0-beta.53: + resolution: {integrity: sha512-Qd9c2p0XKZdgT5AYd+KgAMggJ8ZmCs3JnS9PTMWkyUfteKlfmKtxJbWTHkVakxwXs1Ub7jrRYVeFeF7N0sQxyw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -1692,9 +1683,9 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@oxc-project/runtime@0.97.0': {} + '@oxc-project/runtime@0.101.0': {} - '@oxc-project/types@0.97.0': {} + '@oxc-project/types@0.101.0': {} '@parcel/watcher-android-arm64@2.5.6': optional: true @@ -1757,51 +1748,48 @@ snapshots: '@parcel/watcher-win32-x64': 2.5.6 optional: true - '@rolldown/binding-android-arm64@1.0.0-beta.50': + '@rolldown/binding-android-arm64@1.0.0-beta.53': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-beta.50': + '@rolldown/binding-darwin-arm64@1.0.0-beta.53': optional: true - '@rolldown/binding-darwin-x64@1.0.0-beta.50': + '@rolldown/binding-darwin-x64@1.0.0-beta.53': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-beta.50': + '@rolldown/binding-freebsd-x64@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50': + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50': + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50': + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-beta.50': + '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-beta.50': + '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-beta.50': + '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': dependencies: '@napi-rs/wasm-runtime': 1.1.1 optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50': + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': optional: true - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50': + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50': - optional: true - - '@rolldown/pluginutils@1.0.0-beta.50': {} + '@rolldown/pluginutils@1.0.0-beta.53': {} '@rolldown/pluginutils@1.0.0-rc.3': {} @@ -1860,7 +1848,7 @@ snapshots: dependencies: csstype: 3.2.3 - '@vitejs/plugin-react@5.1.4(rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3))': + '@vitejs/plugin-react@5.1.4(rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -1868,7 +1856,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3) + vite: rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3) transitivePeerDependencies: - supports-color @@ -2383,39 +2371,38 @@ snapshots: reusify@1.1.0: {} - rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3): + rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3): dependencies: - '@oxc-project/runtime': 0.97.0 + '@oxc-project/runtime': 0.101.0 fdir: 6.5.0(picomatch@4.0.3) lightningcss: 1.31.1 picomatch: 4.0.3 postcss: 8.5.6 - rolldown: 1.0.0-beta.50 + rolldown: 1.0.0-beta.53 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 25.3.2 fsevents: 2.3.3 sass: 1.97.3 - rolldown@1.0.0-beta.50: + rolldown@1.0.0-beta.53: dependencies: - '@oxc-project/types': 0.97.0 - '@rolldown/pluginutils': 1.0.0-beta.50 + '@oxc-project/types': 0.101.0 + '@rolldown/pluginutils': 1.0.0-beta.53 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.50 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.50 - '@rolldown/binding-darwin-x64': 1.0.0-beta.50 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.50 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.50 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.50 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.50 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.50 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.50 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.50 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.50 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.50 - '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.50 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.50 + '@rolldown/binding-android-arm64': 1.0.0-beta.53 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.53 + '@rolldown/binding-darwin-x64': 1.0.0-beta.53 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.53 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.53 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.53 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.53 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.53 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.53 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.53 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.53 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.53 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.53 run-parallel@1.2.0: dependencies: @@ -2603,12 +2590,12 @@ snapshots: util-deprecate@1.0.2: {} - vite-tsconfig-paths@6.1.1(rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3))(typescript@5.9.3): + vite-tsconfig-paths@6.1.1(rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3))(typescript@5.9.3): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) - vite: rolldown-vite@7.2.5(@types/node@25.3.2)(sass@1.97.3) + vite: rolldown-vite@7.3.1(@types/node@25.3.2)(sass@1.97.3) transitivePeerDependencies: - supports-color - typescript From fd5f6a74f1748592358d281fd93081c16bcc2271 Mon Sep 17 00:00:00 2001 From: surya Date: Mon, 6 Jul 2026 18:00:25 +0530 Subject: [PATCH 07/11] [fix]: correct encoded SYSTEM XXE regex matching The final branch of _XXE_INJECTION was missing % separators between hex pairs. Pattern %(?:25)?53(?:25)?59... never matched because after consuming %53 the next sub-pattern expected 5 or 2, not %. Fixed by inserting % anchors between each pair so both single-encoded (%53%59%53%54%45%4D) and double-encoded (%2553%2559...) SYSTEM strings match correctly. All existing XXE branches are unaffected. --- .../ai-threat-detection/backend/app/core/features/patterns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py b/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py index 9b02a650..112f69fb 100644 --- a/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py +++ b/PROJECTS/advanced/ai-threat-detection/backend/app/core/features/patterns.py @@ -112,7 +112,7 @@ _XXE_INJECTION = ( r"xmlns\s*:\s*xi\s*=|" r"%(?:25)?3[Cc]!(?:ENTITY|DOCTYPE)|" r"&(?:xxe|xml|ext|file);|" - r"%(?:25)?(?:53|73)(?:25)?(?:59|79)(?:25)?(?:53|73)(?:25)?(?:54|74)(?:25)?(?:45|65)(?:25)?(?:4d|6d))") + r"%(?:25)?(?:53|73)%(?:25)?(?:59|79)%(?:25)?(?:53|73)%(?:25)?(?:54|74)%(?:25)?(?:45|65)%(?:25)?(?:4[Dd]))") _SSRF = ( r"(?:169\.254\.169\.254|" From 1709e0cf0a7ed808bfd0aafc66fbe2e830b43458 Mon Sep 17 00:00:00 2001 From: surya Date: Mon, 6 Jul 2026 18:00:52 +0530 Subject: [PATCH 08/11] [fix]: preserve pre-encoded payloads in simulator requests urllib.parse.quote(path, safe='/?&=') was re-encoding % to %25 in already-encoded attack paths (XXE, XSS, traversal payloads). Replaced with a manual first-? split: path component encoded with safe='/%\' (preserving existing percent sequences and backslash traversal vectors), query string passed through untouched. Covers all 53 attack payloads across 7 simulation modes. Inline comments removed from XXE_PAYLOADS to match the style of all other payload lists. --- .../ai-threat-detection/dev-log/simulate.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py b/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py index afaaa8a0..6eab8177 100755 --- a/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py +++ b/PROJECTS/advanced/ai-threat-detection/dev-log/simulate.py @@ -120,15 +120,10 @@ SSRF_PAYLOADS = [ ] XXE_PAYLOADS = [ - # Classic file disclosure via internal entity "/api/test?data=%3C!DOCTYPE+foo+%5B%3C!ENTITY+xxe+SYSTEM+%22file%3A%2F%2F%2Fetc%2Fpasswd%22%3E%5D%3E", - # SYSTEM keyword targeting /etc/hosts "/api/test?xml=]>", - # XInclude (xmlns:xi) attempt "/api/test?body=", - # URL-encoded ]>&q=&xxe;", ] @@ -169,8 +164,13 @@ ATTACK_POOLS = { def send(target, path, user_agent=None, method="GET"): - encoded_path = urllib.parse.quote(path, safe="/?&=") - url = f"{target}{encoded_path}" + if "?" in path: + _raw_path, _raw_query = path.split("?", 1) + _encoded_path = urllib.parse.quote(_raw_path, safe="/%") + _url_path = f"{_encoded_path}?{_raw_query}" + else: + _url_path = urllib.parse.quote(path, safe="/%\\") + url = f"{target}{_url_path}" ua = user_agent or random.choice(NORMAL_USER_AGENTS) req = urllib.request.Request(url, headers={"User-Agent": ua}) if method == "POST": From b34afd61b976a9bbb156d51854ceec66dd37ab14 Mon Sep 17 00:00:00 2001 From: surya Date: Mon, 6 Jul 2026 18:01:04 +0530 Subject: [PATCH 09/11] [refactor]: relocate backend entrypoint outside bind mount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved entrypoint.sh copy target from /app/entrypoint.sh to /entrypoint.sh in the dev Dockerfile. The dev compose bind mount ./backend:/app overlays /app entirely; placing the entrypoint above that boundary ensures the image-baked script is never shadowed by host directory contents. No startup failure was reproduced — this is a preventive hardening change. --- .../advanced/ai-threat-detection/infra/docker/fastapi.dev | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/infra/docker/fastapi.dev b/PROJECTS/advanced/ai-threat-detection/infra/docker/fastapi.dev index fac6fb6c..375a40ec 100644 --- a/PROJECTS/advanced/ai-threat-detection/infra/docker/fastapi.dev +++ b/PROJECTS/advanced/ai-threat-detection/infra/docker/fastapi.dev @@ -31,11 +31,11 @@ COPY backend/pyproject.toml ./ RUN uv pip install --system -e ".[dev,ml]" COPY backend/ . -COPY infra/docker/entrypoint.sh /app/entrypoint.sh -RUN chmod +x /app/entrypoint.sh && \ +COPY infra/docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh && \ mkdir -p /app/data/models EXPOSE 8000 -ENTRYPOINT ["/app/entrypoint.sh"] +ENTRYPOINT ["/entrypoint.sh"] CMD ["uvicorn", "app.factory:create_app", "--factory", "--host", "0.0.0.0", "--port", "8000", "--reload"] From e8124990af64ba16f3606218334190d4c217d436 Mon Sep 17 00:00:00 2001 From: surya Date: Mon, 6 Jul 2026 18:01:34 +0530 Subject: [PATCH 10/11] [fix]: align pnpm override with lockfile version overrides.vite was pinned to npm:rolldown-vite@7.2.5 while devDependencies and pnpm-lock.yaml both resolved 7.3.1. The mismatch can produce ERR_PNPM_OUTDATED_LOCKFILE on --frozen-lockfile installs. Updated override to 7.3.1 to match the resolved version throughout the lockfile. No lockfile edits required. --- PROJECTS/advanced/ai-threat-detection/frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PROJECTS/advanced/ai-threat-detection/frontend/package.json b/PROJECTS/advanced/ai-threat-detection/frontend/package.json index 16d2bfa4..c7ad49a4 100644 --- a/PROJECTS/advanced/ai-threat-detection/frontend/package.json +++ b/PROJECTS/advanced/ai-threat-detection/frontend/package.json @@ -43,7 +43,7 @@ "vite-tsconfig-paths": "^6.0.5" }, "overrides": { - "vite": "npm:rolldown-vite@7.2.5" + "vite": "npm:rolldown-vite@7.3.1" }, "pnpm": { "onlyBuiltDependencies": [ From b6af44c1f60c5c4efd145fc5b5e2d55dc808d68e Mon Sep 17 00:00:00 2001 From: surya Date: Mon, 6 Jul 2026 18:02:05 +0530 Subject: [PATCH 11/11] [docs]: reorder detection rules by severity score MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _PATTERN_RULES list had XXE_INJECTION (0.82) after XSS (0.80) and CRLF_INJECTION (0.65) after PATH_TRAVERSAL (0.60), placing higher- scored rules below lower-scored ones. Reordered to strict descending order and updated the module docstring to match. No change to scoring behavior — score_request() takes max + boost regardless of list position. --- .../backend/app/core/detection/rules.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py b/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py index 8d2ae22a..a3547393 100644 --- a/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py +++ b/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py @@ -7,9 +7,9 @@ ModSecurity Core Rule Set RuleEngine.score_request evaluates requests against 10 regex-based _PatternRules (LOG4SHELL 0.95, COMMAND_ -INJECTION 0.90, SQL_INJECTION 0.85, XSS 0.80, FILE_ -INCLUSION 0.75, XXE_INJECTION 0.82, SSRF 0.70, CRLF_ -INJECTION 0.65, PATH_TRAVERSAL 0.60, OPEN_REDIRECT 0.55), +INJECTION 0.90, SQL_INJECTION 0.85, XXE_INJECTION 0.82, +XSS 0.80, FILE_INCLUSION 0.75, SSRF 0.70, CRLF_INJECTION +0.65, PATH_TRAVERSAL 0.60, OPEN_REDIRECT 0.55), double-encoding detection (0.40), scanner user-agent signature matching (0.35), and 2 _ThresholdRules (RATE_ANOMALY >100 req/min 0.30, HIGH_ERROR_RATE >50% @@ -78,12 +78,12 @@ _PATTERN_RULES: list[_PatternRule] = [ _PatternRule("LOG4SHELL", LOG4SHELL, 0.95), _PatternRule("COMMAND_INJECTION", COMMAND_INJECTION, 0.90), _PatternRule("SQL_INJECTION", SQLI, 0.85), - _PatternRule("XSS", XSS, 0.80), _PatternRule("XXE_INJECTION", XXE_INJECTION, 0.82), + _PatternRule("XSS", XSS, 0.80), _PatternRule("FILE_INCLUSION", FILE_INCLUSION, 0.75), _PatternRule("SSRF", SSRF, 0.70), - _PatternRule("PATH_TRAVERSAL", PATH_TRAVERSAL, 0.60), _PatternRule("CRLF_INJECTION", CRLF_INJECTION, 0.65), + _PatternRule("PATH_TRAVERSAL", PATH_TRAVERSAL, 0.60), _PatternRule("OPEN_REDIRECT", OPEN_REDIRECT, 0.55), ]