WebUI Internals
MaiBot WebUI is a FastAPI-based web management backend that provides plugin management, configuration editing, authentication, WebSocket communication, and more. This document details its architecture, security mechanisms, and communication protocols.
Overall Architecture
FastAPI Application Factory
Source: src/webui/app.py
create_app() creates a FastAPI instance and configures middleware and routes:
def create_app(host="0.0.0.0", port=8001, enable_static=True) -> FastAPI:
app = FastAPI(title="MaiBot WebUI")
_setup_anti_crawler(app) # Anti-crawler middleware
_setup_cors(app, port) # CORS configuration
_register_api_routes(app) # Register API routes
_setup_robots_txt(app) # robots.txt
if enable_static:
_setup_static_files(app) # SPA static files + path traversal protection
return appCORS Configuration
Only allows localhost origins (development port + service port):
allow_origins = [
"http://localhost:5173", # Vite dev server
"http://127.0.0.1:5173",
f"http://localhost:{port}", # WebUI service port
f"http://127.0.0.1:{port}",
]
allow_credentials = TrueStatic File Security
_resolve_safe_static_file_path() uses resolve() + relative_to() double-check to prevent path traversal.
Authentication and Security
Token Manager
Source: src/webui/core/security.py
TokenManager manages WebUI access tokens:
_create_new_token()— Generates a 64-character hex token (secrets.token_hex(32))get_token()— Gets the current valid tokenverify_token(token)— Verifies token (secrets.compare_digestto prevent timing attacks)update_token(new_token)— Updates token (requires ≥10 characters, including uppercase, lowercase, and special symbols)regenerate_token()— Regenerates a random tokenis_first_setup()— Checks if this is first-time setupmark_setup_completed()— Marks setup as completed
Tokens are stored in data/webui.json (plain-text JSON), relying on file system permissions for protection.
Cookie Authentication
Source: src/webui/core/auth.py
- Cookie Name
maibot_session - Validity Period 7 days
- HttpOnly ✓ (prevents JS access)
- SameSite
lax - Secure Auto-determined based on environment
Authentication flow:
Secure flag determination logic:
- Read configuration
webui.secure_cookie - Check
webui.mode == "production" - Check request header
X-Forwarded-Protoorrequest.url.scheme - HTTP connections force-disable Secure (even if configuration requires it)
Rate Limiter
Source: src/webui/core/rate_limiter.py
In-memory sliding window rate limiter:
- Authentication endpoints — 10 requests/min/IP, 5 consecutive failures → 10-minute ban
- General API — 100 requests/min/IP
WARNING
The rate limiter is in-memory and cannot share state across multiple instances.
Anti-Crawler Middleware
Source: src/webui/middleware/anti_crawler.py
AntiCrawlerMiddleware provides four levels of operation:
false— Disabledbasic— Log only, no blocking (default)loose— 60 requests/min limit, blocks detected crawlersstrict— 15 requests/min limit, stricter detection
Detection dimensions:
- User-Agent: Matches crawler/scanner tool keywords (googlebot, nmap, shodan, etc.)
- HTTP Headers: Detects asset mapping tool characteristic headers (x-scan, x-scanner, etc.)
- IP Whitelist: Supports exact IP, CIDR, and wildcard formats
- Rate Limiting: Sliding window request counting
WebSocket Communication
Unified WebSocket
Source: src/webui/routers/websocket/unified.py
The WebSocket endpoint /ws supports multi-domain subscription and invocation:
WebSocket Authentication
Source: src/webui/routers/websocket/auth.py
Dual-channel authentication mechanism:
- Temporary Token (recommended): First obtain a 60-second-valid temporary token via
GET /api/webui/ws-token, then pass it during the WebSocket handshake - Cookie: Directly use the
maibot_sessionCookie for authentication
Temporary token characteristics:
- 60-second validity period
- One-time use (deleted immediately after verification)
- Verifies that the original session token is still valid
Subscription Domains
logsmain— Log streammaisaka_monitormain— Maisaka reasoning monitoring eventsplugin_progressmain— Plugin operation progresschatchat_id— Chat message stream
Plugin Management IPC
Plugin Runtime Architecture
IPC Protocol
Source: src/plugin_runtime/protocol/
Protocol constants:
PROTOCOL_VERSION = "1.0.0"MIN_SDK_VERSION/MAX_SDK_VERSION: SDK version compatibility range
Envelope structure:
protocol_versionstr— Protocol versionrequest_idstr— Unique request IDmessage_typeMessageType— REQUEST / RESPONSE / BROADCASTmethodstr— RPC method nameplugin_idstr— Plugin IDtimestamp_msint— Timestamptimeout_msint— Timeoutpayloaddict— PayloaderrorRPCError— Error information
Message types:
REQUEST: RPC request from Host → Runner or Runner → HostRESPONSE: Response to a REQUESTBROADCAST: One-to-many notification
Handshake Flow
Transport Layer
Source: src/plugin_runtime/transport/
Frame format: 4-byte big-endian length prefix + msgpack-encoded Envelope.
- UDS (Unix Domain Socket) — Linux / macOS, Default choice
- Named Pipe — Windows, Windows default
- TCP — All platforms, Used when explicitly configured
The transport factory automatically selects the optimal transport based on the runtime platform.
Codec
Source: src/plugin_runtime/protocol/codec.py
Uses msgpack for Envelope serialization and deserialization.
Configuration Hot Reload
WebUI Hot Reload
Source: src/webui/webui_server.py
WebUI registers a callback via _maybe_register_reload_callback(), which is triggered when configuration files change:
- Configuration manager detects TOML file changes
- Triggers
_reload_app()callback - Calls
create_app()to recreate the FastAPI instance - Uvicorn switches to the new application
Plugin Runtime Hot Reload
Source: src/plugin_runtime/integration.py
PluginRuntimeManager monitors configuration and plugin source code changes:
- Configuration change:
_config_reload_callback()is triggered - Dependency analysis:
DependencyPipelinecalculates affected plugins - Restart plan: Determines whether Runner restart is needed based on change type
- Execute restart:
_handle_main_config_reload()coordinates restart of all Supervisors
Route Overview
Source: src/webui/routes.py
All API routes are mounted under the /api/webui prefix:
config_router/config— Configuration read/write (TOML)system_router/system— System control (restart/status)model_router/model— Model managementmemory_router/memory— Long-term memory managementchat_router/chat— WebUI chat APIemoji_router/emoji— Emoji managementexpression_router/expression— Expression managementjargon_router/jargon— Jargon/term managementperson_router/person— Person information managementplugin_router/plugin— Plugin install/uninstall/update/configurestatistics_router/statistics— Statistics dataws_auth_router/ws-token— WebSocket temporary tokenunified_ws_router/ws— Unified WebSocket
Authentication Endpoints
/healthGETNo auth required — Health check/auth/verifyPOSTNo auth required — Verify token and set cookie/auth/logoutPOSTAuth required — Clear cookie/auth/checkGETAuth required — Check authentication status/auth/updatePOSTAuth required — Update token/auth/regeneratePOSTAuth required — Regenerate token/setup/statusGETNo auth required — First-time setup status/setup/completePOSTAuth required — Mark setup as completed
Dependency Injection
Source: src/webui/dependencies.py
FastAPI dependency injection provides authentication and rate limiting:
require_auth— Verifies token in Cookierequire_auth_with_rate_limit— Verifies token + API rate limitingverify_token_optional— Optional verification (not enforced)require_plugin_token— Plugin-specific authenticationcheck_auth_rate_limit— Authentication endpoint rate limitingcheck_api_rate_limit— General API rate limiting
SSRF Protection
Source: src/webui/utils/network_security.py
validate_public_url() blocks access to private addresses:
- 127.0.0.1 / ::1 (localhost)
- 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 (private networks)
- 169.254.0.0/16 (link-local)
- Other reserved address ranges
Applies to plugin installation URLs, image URLs, and other external request scenarios.
Hook System and WebUI Interaction
WebUI interacts with the Hook system through PluginRuntimeManager:
Security Audit Points
- 🔴 High — File upload has no type/size validation ·
routers/memory.py - 🔴 High — WebSocket has no Origin validation ·
routers/websocket/unified.py - 🔴 High — Config API leaks API Key ·
routers/config.py - 🟡 Medium — No CSRF protection · Global
- 🟡 Medium — No CSP headers · Global
- 🟡 Medium — System restart has no secondary confirmation ·
routers/system.py - 🟢 Low — In-memory rate limiter not shared ·
core/rate_limiter.py
WARNING
Production deployments must use a reverse proxy (such as Nginx), configure HTTPS, and set appropriate CORS and security headers.