Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
<meta name="keywords" content="Linux Architecture, protection ring, ring 0, Kernel AI, Linux kernel architecture, Linux system architecture, Linux architecture visualization, Linux kernel internals, Linux architecture learning, interactive Linux architecture, Linux kernel components, system calls visualization, Linux architecture diagram, Linux learning tool, kernel architecture study">
<meta name="author" content="Aleksei Fedorov">
<meta name="robots" content="index, follow">


<!-- Favicon / Icons -->
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/static/images/apple-touch-icon.png">

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://ring-0.sh/">
Expand Down
137 changes: 114 additions & 23 deletions kernel_ai/hooks.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,91 @@
"""Global Flask hooks (CORS, cache headers, request id)."""
"""Global Flask hooks (CORS, cache headers, request id, access log)."""

import json
import logging
import re
import time
from uuid import uuid4

from flask import current_app, g, request

_http_access_logger = logging.getLogger("kernel_ai.http.access")

# --- Request body capture (for web-attack detection) -----------------------
# Only bodies of these methods are inspected.
_BODY_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
# Never read more than this many bytes into memory (skip large/binary uploads).
_MAX_BODY_READ = 64 * 1024
# Truncate the logged (masked) body to this many characters.
_BODY_LOG_MAX = 2048
# Only inspect textual payloads where attack signatures are meaningful.
_BODY_CONTENT_TYPES = ("json", "x-www-form-urlencoded", "text/")
# Keys whose values must never reach the SIEM in clear text.
_SENSITIVE_KEYS = (
"password", "passwd", "pwd", "token", "secret", "api_key", "apikey",
"authorization", "auth", "cookie", "session", "access_token",
"refresh_token", "client_secret", "private_key", "credit", "card",
"cvv", "ssn", "otp",
)
_MASK = "***MASKED***"
# Masks `key=value` / `"key": "value"` pairs in raw/form bodies.
_SENSITIVE_RE = re.compile(
r'(?i)((?:password|passwd|pwd|token|secret|api[_-]?key|authorization|'
r'cookie|session|access[_-]?token|refresh[_-]?token|client[_-]?secret|'
r'private[_-]?key|cvv|ssn|otp)["\']?\s*[:=]\s*["\']?)([^&"\'\s,}]+)'
)


def _is_sensitive_key(key):
lowered = str(key).lower()
return any(token in lowered for token in _SENSITIVE_KEYS)


def _mask_structure(obj):
"""Recursively mask sensitive values in decoded JSON structures."""
if isinstance(obj, dict):
return {
k: (_MASK if _is_sensitive_key(k) else _mask_structure(v))
for k, v in obj.items()
}
if isinstance(obj, list):
return [_mask_structure(v) for v in obj]
return obj


def _mask_text(text):
return _SENSITIVE_RE.sub(lambda m: m.group(1) + _MASK, text)


def _capture_body():
"""Return (masked_body_str_or_None, original_size_or_None).

Reads and caches the raw body so downstream views keep working, masks
secrets, and truncates. Any failure yields (None, size) — logging must
never break request handling.
"""
if request.method not in _BODY_METHODS:
return None, None
size = request.content_length or 0
if size <= 0 or size > _MAX_BODY_READ:
return None, (size or None)
ctype = (request.content_type or "").lower()
if not any(t in ctype for t in _BODY_CONTENT_TYPES):
return None, size
raw = request.get_data(cache=True, as_text=False) or b""
if not raw:
return None, size
text = raw.decode("utf-8", errors="replace")
if "json" in ctype:
try:
masked = json.dumps(_mask_structure(json.loads(text)), ensure_ascii=False)
except Exception:
masked = _mask_text(text)
else:
masked = _mask_text(text)
if len(masked) > _BODY_LOG_MAX:
masked = masked[:_BODY_LOG_MAX] + "...[truncated]"
return masked, len(raw)


def register_hooks(app):
"""Register after_request handler for CORS and static/HTML cache control."""
Expand All @@ -17,6 +95,14 @@ def assign_request_id():
incoming = (request.headers.get("X-Request-ID") or "").strip()
g.request_id = incoming or uuid4().hex
g.request_started_ns = time.time_ns()
# Capture body here: the stream is still available and gets cached
# for the view. Guarded so it can never break the request.
g.req_body_content = None
g.req_body_bytes = None
try:
g.req_body_content, g.req_body_bytes = _capture_body()
except Exception: # pragma: no cover - defensive
pass

@app.after_request
def add_headers(response):
Expand All @@ -29,28 +115,33 @@ def add_headers(response):
source_ip = request.headers.get("X-Forwarded-For", request.remote_addr)
if source_ip and "," in source_ip:
source_ip = source_ip.split(",")[0].strip()
_http_access_logger.info(
"http_request",
extra={
"event_data": {
"@timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"event.category": "web",
"event.type": "access",
"event.dataset": "kernel_ai.http",
"request.id": request_id,
"source.ip": source_ip,
"http.request.method": request.method,
"http.version": request.environ.get("SERVER_PROTOCOL", ""),
"host.name": request.host,
"url.path": request.path,
"url.query": (request.query_string or b"").decode("utf-8", errors="ignore"),
"user_agent.original": request.headers.get("User-Agent"),
"http.response.status_code": response.status_code,
"service.environment": current_app.config.get("ENV", "production"),
"event.duration": duration_ns,
}
},
)

event_data = {
"@timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"event.category": "web",
"event.type": "access",
"event.dataset": "kernel_ai.http",
"request.id": request_id,
"source.ip": source_ip,
"http.request.method": request.method,
"http.version": request.environ.get("SERVER_PROTOCOL", ""),
"host.name": request.host,
"url.path": request.path,
"url.query": (request.query_string or b"").decode("utf-8", errors="ignore"),
"user_agent.original": request.headers.get("User-Agent"),
"http.response.status_code": response.status_code,
"service.environment": current_app.config.get("ENV", "production"),
"event.duration": duration_ns,
}
body_content = getattr(g, "req_body_content", None)
if body_content:
event_data["http.request.body.content"] = body_content
body_bytes = getattr(g, "req_body_bytes", None)
if body_bytes:
event_data["http.request.body.bytes"] = body_bytes

_http_access_logger.info("http_request", extra={"event_data": event_data})

response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
response.headers["Access-Control-Allow-Headers"] = "Content-Type"
Expand Down
4 changes: 4 additions & 0 deletions templates/linux-crypto-subsystem.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Linux Crypto Kernel Subsystem - Linux Kernel Architecture Visualization</title>
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/static/images/apple-touch-icon.png">
<meta name="description" content="Interactive Linux crypto kernel subsystem page: request origin, crypto lookup, algorithm competition, implementation selection, and hardware offload in Linux kernel architecture.">
<meta name="keywords" content="
linux architecture,
Expand Down
4 changes: 4 additions & 0 deletions templates/linux-memory-subsystem.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Linux Memory Kernel Subsystem - Linux Kernel Architecture Visualization</title>
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/static/images/apple-touch-icon.png">
<meta name="description" content="Interactive Linux memory kernel subsystem page: /proc/meminfo accounting, page cache, anonymous memory, slab, swap and task RSS strips.">
<meta name="keywords" content="
linux memory subsystem,
Expand Down
4 changes: 4 additions & 0 deletions templates/linux-processes-subsystem.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Linux Processes Kernel Subsystem - Linux Kernel Architecture Visualization</title>
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/static/images/apple-touch-icon.png">
<meta name="description" content="Interactive Linux processes subsystem page: syscall interception, network tracing, and security hooks visualized as a neural layer above the kernel.">
<meta name="keywords" content="
linux processes subsystem,
Expand Down
4 changes: 4 additions & 0 deletions templates/linux-security-subsystem.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Linux Security Kernel Subsystem - Linux Kernel Architecture Visualization</title>
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/static/images/apple-touch-icon.png">
<meta name="description" content="Interactive Linux security kernel subsystem page: threat decision pipeline, LSM and seccomp checks, process trust graph, and attack surface map.">
<meta name="keywords" content="
linux security subsystem,
Expand Down
Loading