Skip to content

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:

python
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 app

CORS Configuration

Only allows localhost origins (development port + service port):

python
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 = True

Static 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:

MethodDescription
_create_new_token()Generates a 64-character hex token (secrets.token_hex(32))
get_token()Gets the current valid token
verify_token(token)Verifies token (secrets.compare_digest to prevent timing attacks)
update_token(new_token)Updates token (requires ≥10 characters, including uppercase, lowercase, and special symbols)
regenerate_token()Regenerates a random token
is_first_setup()Checks if this is first-time setup
mark_setup_completed()Marks setup as completed

Tokens are stored in data/webui.json (plain-text JSON), relying on file system permissions for protection.

Source: src/webui/core/auth.py

ConfigurationValue
Cookie Namemaibot_session
Validity Period7 days
HttpOnly✓ (prevents JS access)
SameSitelax
SecureAuto-determined based on environment

Authentication flow:

Secure flag determination logic:

  1. Read configuration webui.secure_cookie
  2. Check webui.mode == "production"
  3. Check request header X-Forwarded-Proto or request.url.scheme
  4. 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:

ScenarioLimitBan
Authentication endpoints10 requests/min/IP5 consecutive failures → 10-minute ban
General API100 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:

ModeDescription
falseDisabled
basicLog only, no blocking (default)
loose60 requests/min limit, blocks detected crawlers
strict15 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:

  1. Temporary Token (recommended): First obtain a 60-second-valid temporary token via GET /api/webui/ws-token, then pass it during the WebSocket handshake
  2. Cookie: Directly use the maibot_session Cookie 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

DomainTopicDescription
logsmainLog stream
maisaka_monitormainMaisaka reasoning monitoring events
plugin_progressmainPlugin operation progress
chatchat_idChat 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:

FieldTypeDescription
protocol_versionstrProtocol version
request_idstrUnique request ID
message_typeMessageTypeREQUEST / RESPONSE / BROADCAST
methodstrRPC method name
plugin_idstrPlugin ID
timestamp_msintTimestamp
timeout_msintTimeout
payloaddictPayload
errorRPCErrorError information

Message types:

  • REQUEST: RPC request from Host → Runner or Runner → Host
  • RESPONSE: Response to a REQUEST
  • BROADCAST: One-to-many notification

Handshake Flow

Transport Layer

Source: src/plugin_runtime/transport/

Frame format: 4-byte big-endian length prefix + msgpack-encoded Envelope.

TransportPlatformDescription
UDS (Unix Domain Socket)Linux / macOSDefault choice
Named PipeWindowsWindows default
TCPAll platformsUsed 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:

  1. Configuration manager detects TOML file changes
  2. Triggers _reload_app() callback
  3. Calls create_app() to recreate the FastAPI instance
  4. Uvicorn switches to the new application

Plugin Runtime Hot Reload

Source: src/plugin_runtime/integration.py

PluginRuntimeManager monitors configuration and plugin source code changes:

  1. Configuration change: _config_reload_callback() is triggered
  2. Dependency analysis: DependencyPipeline calculates affected plugins
  3. Restart plan: Determines whether Runner restart is needed based on change type
  4. 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:

Route ModulePrefixDescription
config_router/configConfiguration read/write (TOML)
system_router/systemSystem control (restart/status)
model_router/modelModel management
memory_router/memoryLong-term memory management
chat_router/chatWebUI chat API
emoji_router/emojiEmoji management
expression_router/expressionExpression management
jargon_router/jargonJargon/term management
person_router/personPerson information management
plugin_router/pluginPlugin install/uninstall/update/configure
statistics_router/statisticsStatistics data
ws_auth_router/ws-tokenWebSocket temporary token
unified_ws_router/wsUnified WebSocket

Authentication Endpoints

EndpointMethodAuth RequiredDescription
/healthGETHealth check
/auth/verifyPOSTVerify token and set cookie
/auth/logoutPOSTClear cookie
/auth/checkGETCheck authentication status
/auth/updatePOSTUpdate token
/auth/regeneratePOSTRegenerate token
/setup/statusGETFirst-time setup status
/setup/completePOSTMark setup as completed

Dependency Injection

Source: src/webui/dependencies.py

FastAPI dependency injection provides authentication and rate limiting:

DependencyDescription
require_authVerifies token in Cookie
require_auth_with_rate_limitVerifies token + API rate limiting
verify_token_optionalOptional verification (not enforced)
require_plugin_tokenPlugin-specific authentication
check_auth_rate_limitAuthentication endpoint rate limiting
check_api_rate_limitGeneral 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

SeverityIssueLocation
🔴 HighFile upload has no type/size validationrouters/memory.py
🔴 HighWebSocket has no Origin validationrouters/websocket/unified.py
🔴 HighConfig API leaks API Keyrouters/config.py
🟡 MediumNo CSRF protectionGlobal
🟡 MediumNo CSP headersGlobal
🟡 MediumSystem restart has no secondary confirmationrouters/system.py
🟢 LowIn-memory rate limiter not sharedcore/rate_limiter.py

WARNING

Production deployments must use a reverse proxy (such as Nginx), configure HTTPS, and set appropriate CORS and security headers.