This is an automated email from the ASF dual-hosted git repository.

FreeOnePlus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-mcp-server.git


The following commit(s) were added to refs/heads/master by this push:
     new d455473  fix: remove default authentication secrets (#113)
d455473 is described below

commit d455473d8238a127c4c8178c23babedecab4278e
Author: Yijia Su <[email protected]>
AuthorDate: Wed Jul 29 19:53:21 2026 +0800

    fix: remove default authentication secrets (#113)
---
 .env.example                                       |  23 +--
 CHANGELOG.md                                       |   2 +
 README.md                                          |  57 ++++---
 docker-compose.yml                                 |   6 +-
 doris_mcp_server/auth/token_manager.py             | 101 ++++--------
 doris_mcp_server/auth/token_security_middleware.py |   9 ++
 doris_mcp_server/utils/config.py                   |  88 ++++++++++-
 doris_mcp_server/utils/db.py                       |  42 -----
 doris_mcp_server/utils/secret_policy.py            |  85 ++++++++++
 test/security/test_effective_auth_config.py        |   6 +-
 test/security/test_static_token_bootstrap.py       | 171 +++++++++++++++++++++
 test/security/test_token_management_auth.py        |   2 +-
 tokens.json                                        |  66 +-------
 13 files changed, 435 insertions(+), 223 deletions(-)

diff --git a/.env.example b/.env.example
index bc9cd56..2b37f3d 100644
--- a/.env.example
+++ b/.env.example
@@ -59,7 +59,7 @@ DORIS_MAX_CONNECTION_AGE=3600
 
 # Legacy configuration - kept for backward compatibility
 # AUTH_TYPE is now deprecated - use individual switches above
-AUTH_TYPE=token
+# AUTH_TYPE=token
 
 # Token Authentication (Default method - simple and effective)
 ENABLE_TOKEN_AUTH=false
@@ -79,6 +79,9 @@ TOKEN_FILE_PATH=tokens.json
 ENABLE_TOKEN_EXPIRY=true
 DEFAULT_TOKEN_EXPIRY_HOURS=720
 TOKEN_HASH_ALGORITHM=sha256
+# No static bearer token is shipped. Generate one outside source control:
+# python -c 'import secrets; print(secrets.token_urlsafe(32))'
+# TOKEN_ADMIN=<paste-generated-value-here>
 
 # ===================================================================
 # Token Management Security Configuration (NEW in v0.6.0) - CRITICAL SECURITY 
SETTINGS
@@ -87,7 +90,7 @@ TOKEN_HASH_ALGORITHM=sha256
 # HTTP Token Management Endpoints (DISABLED BY DEFAULT FOR SECURITY)
 # WARNING: These endpoints allow creation, deletion, and management of 
authentication tokens
 # Only enable if you need HTTP-based token management and understand the 
security implications
-ENABLE_HTTP_TOKEN_MANAGEMENT=true
+ENABLE_HTTP_TOKEN_MANAGEMENT=false
 
 # Admin Authentication Token (REQUIRED if HTTP token management is enabled)
 # This token is required to access HTTP token management endpoints
@@ -305,8 +308,8 @@ DORIS_OAUTH_TRUSTED_PROXY_CIDRS=
 # DORIS_OAUTH_TRUST_PROXY_HEADERS=true
 # DORIS_OAUTH_TRUSTED_PROXY_CIDRS=10.0.0.0/8,192.168.0.0/16
 
-# Legacy token settings (for backward compatibility)
-TOKEN_SECRET=your_secret_key_here
+# Legacy token settings (deprecated; no default secret is provided)
+TOKEN_SECRET=
 TOKEN_EXPIRY=3600
 
 # SQL security check
@@ -443,10 +446,10 @@ TEMP_FILES_DIR=tmp
 #    - NEW: Enable individual authentication methods using ENABLE_TOKEN_AUTH, 
ENABLE_JWT_AUTH, ENABLE_OAUTH_AUTH
 #    - When all methods are disabled, ALL requests are allowed with anonymous 
access
 #    - Authentication methods work independently - any one succeeding allows 
access
-#    - Token Auth: Change default tokens (DEFAULT_ADMIN_TOKEN, etc.) in 
production
+#    - Token Auth: Configure deployment-specific TOKEN_<ID> values before 
enabling it
 #    - JWT Auth: Change JWT_SECRET_KEY and JWT_REFRESH_SECRET_KEY in production
 #    - OAuth Auth: Configure OAuth provider settings and secure client secrets
-#    - Must change TOKEN_SECRET in production environment (legacy 
compatibility)
+#    - TOKEN_SECRET is deprecated and intentionally has no default value
 #    - Adjust BLOCKED_KEYWORDS according to business needs
 #    - Enable ENABLE_SECURITY_CHECK and ENABLE_MASKING
 #    - NEW v0.6.0: Token Management Security (CRITICAL):
@@ -488,7 +491,7 @@ TEMP_FILES_DIR=tmp
 #    
 #    Token Authentication (ENABLE_TOKEN_AUTH=true) - Recommended for most use 
cases:
 #    - Simple and secure token-based authentication
-#    - Configurable default tokens via environment variables
+#    - No default credential; at least one active high-entropy token is 
required
 #    - Support for custom tokens via TOKEN_* environment variables
 #    - Token file configuration via tokens.json
 #    - Built-in token management HTTP endpoints
@@ -576,9 +579,7 @@ TEMP_FILES_DIR=tmp
 #    # NEVER disable admin auth in production:
 #    # REQUIRE_ADMIN_AUTH=false  # DANGEROUS!
 #    
-#    # NEVER use weak admin tokens:
-#    # TOKEN_MANAGEMENT_ADMIN_TOKEN=admin  # DANGEROUS!
-#    # TOKEN_MANAGEMENT_ADMIN_TOKEN=123456  # DANGEROUS!
+#    # NEVER use short, repeated, or placeholder admin tokens.
 #    
 #    📊 ENDPOINT SECURITY TESTING:
 #    # Test security (should fail):
@@ -590,7 +591,7 @@ TEMP_FILES_DIR=tmp
 #    # Expected: 401 Unauthorized (missing admin token)
 #    
 #    # Test with valid auth (should succeed if enabled):
-#    curl -H "Authorization: Bearer your-admin-token" 
http://127.0.0.1:3000/token/stats
+#    curl -H "Authorization: Bearer $TOKEN_MANAGEMENT_ADMIN_TOKEN" 
http://127.0.0.1:3000/token/stats
 #    # Expected: 200 OK with token statistics
 #    
 #    🔍 MONITORING & AUDITING:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc211d7..6f50783 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -50,6 +50,8 @@ under **Unreleased** until a new version is selected and 
published.
 - Corrected resource and prompt error semantics and tool `isError` results.
 - Removed admin-token query authentication and dashboard URL propagation;
   management endpoints now accept admin credentials only in headers.
+- Removed shipped static credentials and the legacy default secret; static and
+  management token modes now require explicit high-entropy credentials.
 - Released Doris connections on SQL profile, data freshness, and access
   analysis paths.
 - Improved Doris 4 role metadata compatibility and query recovery behavior.
diff --git a/README.md b/README.md
index a2574a1..36fc9bc 100644
--- a/README.md
+++ b/README.md
@@ -135,11 +135,12 @@ Access the **Web-Based Token Management Dashboard** for 
enterprise-grade token a
 - **Admin Authentication**: Requires `TOKEN_MANAGEMENT_ADMIN_TOKEN` for access
 - **Configuration Prerequisites**:
   ```bash
-  # Required environment variables
-  ENABLE_HTTP_TOKEN_MANAGEMENT=true
-  ENABLE_TOKEN_AUTH=true
-  TOKEN_MANAGEMENT_ADMIN_TOKEN=your_secure_admin_token
-  TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1
+  # Generate separate high-entropy credentials; do not commit them.
+  export TOKEN_ADMIN="$(python -c 'import secrets; 
print(secrets.token_urlsafe(32))')"
+  export TOKEN_MANAGEMENT_ADMIN_TOKEN="$(python -c 'import secrets; 
print(secrets.token_urlsafe(32))')"
+  export ENABLE_HTTP_TOKEN_MANAGEMENT=true
+  export ENABLE_TOKEN_AUTH=true
+  export TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1
   ```
 
 #### **Interface Access**
@@ -149,7 +150,7 @@ tokens are rejected and must not be placed in URLs, browser 
history, or access
 logs.
 
 ```bash
-curl -H "Authorization: Bearer your_secure_admin_token" \
+curl -H "Authorization: Bearer $TOKEN_MANAGEMENT_ADMIN_TOKEN" \
   http://127.0.0.1:3000/token/stats
 ```
 
@@ -200,9 +201,10 @@ export DORIS_USER="root"
 export DORIS_PASSWORD="your_password"
 
 # Token Management Interface (Security-Critical)
+export TOKEN_ADMIN="$(python -c 'import secrets; 
print(secrets.token_urlsafe(32))')"
+export TOKEN_MANAGEMENT_ADMIN_TOKEN="$(python -c 'import secrets; 
print(secrets.token_urlsafe(32))')"
 export ENABLE_HTTP_TOKEN_MANAGEMENT=true
 export ENABLE_TOKEN_AUTH=true
-export TOKEN_MANAGEMENT_ADMIN_TOKEN="your_secure_admin_token"
 export TOKEN_MANAGEMENT_ALLOWED_IPS="127.0.0.1,::1"
 
 # Then start with simplified command
@@ -271,12 +273,10 @@ cp .env.example .env
     *   `DORIS_OAUTH_BASE_URL`: Public base URL used by Doris-backed OAuth 
discovery and token endpoints
     *   `TOKEN_FILE_PATH`: Path to tokens.json file for token management 
(default: tokens.json)
     *   `TOKEN_HOT_RELOAD`: Enable hot reloading of token configuration 
(default: true)
-    *   `DEFAULT_ADMIN_TOKEN`: Default admin token (customizable via env)
-    *   `DEFAULT_ANALYST_TOKEN`: Default analyst token (customizable via env)
-    *   `DEFAULT_READONLY_TOKEN`: Default readonly token (customizable via env)
+    *   `TOKEN_<ID>`: Explicit static bearer token; each active token must be a
+        securely generated value of at least 32 characters
 *   **Legacy Security Configuration**:
     *   `AUTH_TYPE`: Legacy authentication type (token/basic/oauth, deprecated 
- use individual switches)
-    *   `TOKEN_SECRET`: Legacy token secret key (use token-based auth instead)
     *   `ENABLE_SECURITY_CHECK`: Enable/disable SQL security validation 
(default: true)
     *   `BLOCKED_KEYWORDS`: Comma-separated list of blocked SQL keywords
     *   `ENABLE_MASKING`: Enable data masking (default: true)
@@ -600,6 +600,9 @@ The Doris MCP Server includes a comprehensive 
enterprise-grade security framewor
 Configure the new authentication system with granular control:
 
 ```bash
+# Generate a deployment-specific token before enabling static authentication.
+export TOKEN_ADMIN="$(python -c 'import secrets; 
print(secrets.token_urlsafe(32))')"
+
 # Individual Authentication Control (New in v0.6.0)
 ENABLE_TOKEN_AUTH=true          # Enable token-based authentication
 ENABLE_JWT_AUTH=false           # Enable JWT authentication  
@@ -609,16 +612,14 @@ ENABLE_OAUTH_AUTH=false         # Enable OAuth 
authentication
 TOKEN_FILE_PATH=tokens.json     # Token configuration file
 TOKEN_HOT_RELOAD=true          # Enable hot reloading
 
-# Default Tokens (Customizable via environment)
-DEFAULT_ADMIN_TOKEN=doris_admin_token_123456
-DEFAULT_ANALYST_TOKEN=doris_analyst_token_123456
-DEFAULT_READONLY_TOKEN=doris_readonly_token_123456
-
 # Legacy Configuration (Deprecated)
 # AUTH_TYPE=token               # Use individual switches instead
-# TOKEN_SECRET=your_secret_key  # Use token-based auth instead
 ```
 
+The repository ships no usable static token or legacy secret. Startup fails
+when static token authentication is enabled without at least one active,
+high-entropy `TOKEN_<ID>` value or an equivalent entry in `TOKEN_FILE_PATH`.
+
 ### Doris-Backed OAuth Authentication
 
 Doris-backed OAuth is a separate OAuth mode where Doris itself is the 
authorization backend. The MCP client discovers this server's OAuth metadata, 
the user signs in with a Doris username and password, the server validates 
those credentials by creating a per-user Doris connection pool, and issued 
`doa_` access tokens route tool calls through that Doris user's pool. MCP 
scopes control which MCP operations can be called; Doris RBAC controls which 
catalogs, databases, tables, and metadata t [...]
@@ -926,9 +927,9 @@ custom_rule = {
 #### Environment Variables
 
 ```bash
-# .env file
-AUTH_TYPE=token
-TOKEN_SECRET=your_jwt_secret_key
+# Generate this outside source control, then inject it into the process.
+export TOKEN_SECURITY_ADMIN="$(python -c 'import secrets; 
print(secrets.token_urlsafe(32))')"
+export ENABLE_TOKEN_AUTH=true
 ENABLE_MASKING=true
 MAX_RESULT_ROWS=10000
 BLOCKED_SQL_OPERATIONS=DROP,DELETE,TRUNCATE,ALTER
@@ -1393,10 +1394,6 @@ DORIS_BE_WEBSERVER_PORT=8040
 ```bash
 # Enable data masking
 ENABLE_MASKING=true
-# Set authentication type
-AUTH_TYPE=token
-# Configure token secret
-TOKEN_SECRET=your_secret_key
 # Set maximum result rows
 MAX_RESULT_ROWS=10000
 ```
@@ -1677,7 +1674,7 @@ cat logs/doris_mcp_server_critical.log
      "tokens": [
        {
          "token_id": "tenant-alpha",
-         "token": "tenant_alpha_secure_token_123",
+         "token": "<generated-deployment-token-at-least-32-characters>",
          "description": "Tenant Alpha database access",
          "expires_hours": null,
          "is_active": true,
@@ -1708,8 +1705,8 @@ cat logs/doris_mcp_server_critical.log
 5. **Multi-Tenant Usage**:
    ```bash
    # Different tokens access different databases automatically
-   curl -H "Authorization: Bearer tenant_alpha_secure_token_123" 
http://localhost:3000/mcp
-   curl -H "Authorization: Bearer tenant_beta_secure_token_456" 
http://localhost:3000/mcp
+   curl -H "Authorization: Bearer $TOKEN_TENANT_ALPHA" 
http://localhost:3000/mcp
+   curl -H "Authorization: Bearer $TOKEN_TENANT_BETA" http://localhost:3000/mcp
    ```
 
 ### Q: How is Doris-backed OAuth different from external OAuth/OIDC?
@@ -1781,13 +1778,13 @@ tail -f logs/doris_mcp_server_info.log | grep "hot 
reload"
 # ✓ Admin authentication enabled in configuration
 
 # Enable HTTP token management (disabled by default)
+export TOKEN_MANAGEMENT_ADMIN_TOKEN="$(python -c 'import secrets; 
print(secrets.token_urlsafe(32))')"
 export ENABLE_HTTP_TOKEN_MANAGEMENT=true
-export TOKEN_MANAGEMENT_ADMIN_TOKEN=your_secure_admin_token
 export REQUIRE_ADMIN_AUTH=true
 export TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1
 
 # Access with proper authentication
-curl -H "Authorization: Bearer your_secure_admin_token" 
http://127.0.0.1:3000/token/stats
+curl -H "Authorization: Bearer $TOKEN_MANAGEMENT_ADMIN_TOKEN" 
http://127.0.0.1:3000/token/stats
 
 # Demo page (local access only, with authentication)
 # Access: http://127.0.0.1:3000/token/demo
@@ -1803,7 +1800,7 @@ curl -H "Authorization: Bearer your_secure_admin_token" 
http://127.0.0.1:3000/to
      "tokens": [
        {
          "token_id": "dev-token",
-         "token": "dev_secure_token_123",
+         "token": "<generated-development-token-at-least-32-characters>",
          "description": "Development environment access",
          "expires_hours": 24,
          "is_active": true
diff --git a/docker-compose.yml b/docker-compose.yml
index 002cfdf..4127063 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -40,8 +40,8 @@ services:
       - DORIS_MAX_CONNECTIONS=20
       
       # Security configuration
-      - AUTH_TYPE=token
-      - TOKEN_SECRET=your_secret_key_here
+      - ENABLE_TOKEN_AUTH=true
+      - TOKEN_ADMIN=${MCP_STATIC_TOKEN:?Set MCP_STATIC_TOKEN to a securely 
generated value of at least 32 characters}
       - MAX_RESULT_ROWS=10000
       
       # Performance configuration
@@ -215,4 +215,4 @@ networks:
     driver: bridge
     ipam:
       config:
-        - subnet: 172.20.0.0/16 
\ No newline at end of file
+        - subnet: 172.20.0.0/16
diff --git a/doris_mcp_server/auth/token_manager.py 
b/doris_mcp_server/auth/token_manager.py
index 4717744..bbd11a4 100644
--- a/doris_mcp_server/auth/token_manager.py
+++ b/doris_mcp_server/auth/token_manager.py
@@ -34,6 +34,10 @@ from typing import Dict, List, Optional, Any
 from pathlib import Path
 
 from ..utils.logger import get_logger
+from ..utils.secret_policy import (
+    is_static_token_environment_variable,
+    validate_high_entropy_secret,
+)
 from ..utils.security import RESERVED_DORIS_OAUTH_TOKEN_PREFIX, SecurityLevel
 
 
@@ -103,11 +107,22 @@ class TokenManager:
         self._file_last_modified = 0
         self._hot_reload_task = None
         
-        # Initialize with default tokens if none exist
-        self._initialize_default_tokens()
-        
         # Load tokens from configuration
         self._load_tokens()
+
+        effective_auth = getattr(config, "effective_auth", None)
+        token_auth_enabled = getattr(
+            effective_auth,
+            "enable_token_auth",
+            getattr(config.security, "enable_token_auth", False),
+        )
+        if token_auth_enabled and not any(
+            token_info.is_active for token_info in self._tokens.values()
+        ):
+            raise ValueError(
+                "Token authentication is enabled but no active static token is 
configured. "
+                "Set a high-entropy TOKEN_<ID> environment variable or provide 
one in tokens.json."
+            )
         
         # Start hot reload monitoring
         if self.enable_hot_reload:
@@ -122,64 +137,6 @@ class TokenManager:
                 f"'{RESERVED_DORIS_OAUTH_TOKEN_PREFIX}'"
             )
     
-    def _initialize_default_tokens(self):
-        """Initialize default tokens for basic authentication (configurable 
via environment)"""
-        # Default token configurations (can be overridden by environment 
variables)
-        default_tokens = [
-            {
-                'token_id': 'admin-token',
-                'token': os.getenv('DEFAULT_ADMIN_TOKEN', 
'doris_admin_token_123456'),
-                'description': os.getenv('DEFAULT_ADMIN_DESCRIPTION', 'Default 
admin API access token'),
-                'expires_hours': None  # Never expires
-            },
-            {
-                'token_id': 'analyst-token', 
-                'token': os.getenv('DEFAULT_ANALYST_TOKEN', 
'doris_analyst_token_123456'),
-                'description': os.getenv('DEFAULT_ANALYST_DESCRIPTION', 
'Default data analysis API access token'),
-                'expires_hours': None  # Never expires
-            },
-            {
-                'token_id': 'readonly-token',
-                'token': os.getenv('DEFAULT_READONLY_TOKEN', 
'doris_readonly_token_123456'),
-                'description': os.getenv('DEFAULT_READONLY_DESCRIPTION', 
'Default read-only API access token'),
-                'expires_hours': None  # Never expires
-            }
-        ]
-        
-        
-        # Only add default tokens if no custom tokens are defined via 
environment variables
-        # Check if any TOKEN_* environment variables exist (excluding system 
and legacy configs)
-        excluded_prefixes = ('DEFAULT_', 'TOKEN_FILE_PATH', 'TOKEN_HASH_')
-        excluded_vars = {'TOKEN_SECRET', 'TOKEN_EXPIRY'}
-        
-        custom_tokens_exist = any(
-            key.startswith('TOKEN_') and 
-            not key.startswith(excluded_prefixes) and 
-            not key.endswith(('_EXPIRES_HOURS', '_DESCRIPTION')) and
-            key not in excluded_vars
-            for key in os.environ.keys()
-        )
-        
-        # Also check if token file exists and has content
-        token_file_exists = False
-        if os.path.exists(self.token_file_path):
-            try:
-                with open(self.token_file_path, 'r') as f:
-                    content = f.read().strip()
-                    if content and content != '{}':
-                        token_file_exists = True
-            except:
-                pass
-        
-        # Add default tokens only if no custom configuration exists
-        if not custom_tokens_exist and not token_file_exists:
-            for token_config in default_tokens:
-                self._add_token_from_config(token_config)
-            
-            self.logger.info(f"Initialized {len(default_tokens)} default 
tokens (no custom config found)")
-        else:
-            self.logger.info("Skipped default tokens initialization (custom 
tokens detected)")
-    
     def _add_token_from_config(self, token_config: Dict[str, Any]):
         """Add token from configuration with optional database binding"""
         try:
@@ -216,6 +173,10 @@ class TokenManager:
             # Hash the token
             raw_token = token_config['token']
             self._validate_static_token_prefix(raw_token)
+            validate_high_entropy_secret(
+                raw_token,
+                setting=f"static token '{token_info.token_id}'",
+            )
             token_hash = self._hash_token(raw_token)
             
             # Store token
@@ -251,17 +212,8 @@ class TokenManager:
         token_prefixes = set()
         
         # Find all TOKEN_ environment variables (exclude legacy and system 
variables)
-        excluded_token_vars = {
-            'TOKEN_SECRET',           # Legacy token secret
-            'TOKEN_EXPIRY',           # Legacy token expiry
-            'TOKEN_FILE_PATH',        # System config
-            'TOKEN_HASH_ALGORITHM'    # System config
-        }
-        
         for key in os.environ:
-            if (key.startswith('TOKEN_') and 
-                not key.endswith(('_EXPIRES_HOURS', '_DESCRIPTION')) and
-                key not in excluded_token_vars):
+            if is_static_token_environment_variable(key):
                 token_id = key[6:]  # Remove 'TOKEN_' prefix
                 token_prefixes.add(token_id)
         
@@ -398,6 +350,10 @@ class TokenManager:
             else:
                 raw_token = self.generate_token()
             self._validate_static_token_prefix(raw_token)
+            validate_high_entropy_secret(
+                raw_token,
+                setting=f"static token '{token_id}'",
+            )
             
             # Calculate expiration
             expires_at = None
@@ -816,9 +772,6 @@ class TokenManager:
                         self._tokens.clear()
                         self._token_ids.clear()
                         
-                        # Reinitialize default tokens
-                        self._initialize_default_tokens()
-                        
                         # Load from file
                         self._load_tokens_from_file()
                         
diff --git a/doris_mcp_server/auth/token_security_middleware.py 
b/doris_mcp_server/auth/token_security_middleware.py
index d9dbc3b..b737e76 100644
--- a/doris_mcp_server/auth/token_security_middleware.py
+++ b/doris_mcp_server/auth/token_security_middleware.py
@@ -33,6 +33,7 @@ from starlette.responses import JSONResponse
 
 from ..utils.logger import get_logger
 from ..utils.config import DorisConfig
+from ..utils.secret_policy import validate_high_entropy_secret
 
 
 class TokenSecurityMiddleware:
@@ -44,6 +45,14 @@ class TokenSecurityMiddleware:
         
         # Initialize admin token hash if provided
         self._admin_token_hash = None
+        if (
+            config.security.enable_http_token_management
+            and config.security.require_admin_auth
+        ):
+            validate_high_entropy_secret(
+                config.security.token_management_admin_token,
+                setting="TOKEN_MANAGEMENT_ADMIN_TOKEN",
+            )
         if config.security.token_management_admin_token:
             self._admin_token_hash = 
self._hash_token(config.security.token_management_admin_token)
             
diff --git a/doris_mcp_server/utils/config.py b/doris_mcp_server/utils/config.py
index 7031aca..d2af765 100644
--- a/doris_mcp_server/utils/config.py
+++ b/doris_mcp_server/utils/config.py
@@ -37,6 +37,10 @@ except ImportError:
     load_dotenv = None
 
 from .logger import get_logger
+from .secret_policy import (
+    is_static_token_environment_variable,
+    validate_high_entropy_secret,
+)
 
 
 class AuthConfigError(ValueError):
@@ -276,7 +280,7 @@ class SecurityConfig:
     
     # Legacy configuration (kept for backward compatibility)
     auth_type: str = "token"  # jwt, token, basic, oauth (deprecated: use 
individual switches)
-    token_secret: str = "default_secret"  # Legacy token secret for backward 
compatibility
+    token_secret: str = ""  # Deprecated legacy field; no usable default secret
     token_expiry: int = 3600
     
     # Enhanced Token Authentication Configuration
@@ -1290,6 +1294,73 @@ def build_auth_config_inputs(config: DorisConfig, 
requested_workers: int | None
     )
 
 
+def _configured_static_tokens(
+    security_config: SecurityConfig,
+) -> list[tuple[str, Any, bool]]:
+    """Load source labels, raw values, and active flags for configured static 
tokens."""
+    configured: list[tuple[str, Any, bool]] = []
+    for name, value in os.environ.items():
+        if is_static_token_environment_variable(name):
+            configured.append((name, value, True))
+
+    token_file = Path(security_config.token_file_path)
+    if not token_file.exists():
+        return configured
+
+    try:
+        token_data = json.loads(token_file.read_text(encoding="utf-8"))
+    except (OSError, json.JSONDecodeError) as exc:
+        raise AuthConfigError(f"Unable to load static token file {token_file}: 
{exc}") from exc
+
+    if isinstance(token_data, dict) and "tokens" in token_data:
+        token_entries = token_data["tokens"]
+    elif isinstance(token_data, list):
+        token_entries = token_data
+    else:
+        raise AuthConfigError(
+            f"Static token file {token_file} must contain a tokens array"
+        )
+    if not isinstance(token_entries, list):
+        raise AuthConfigError(
+            f"Static token file {token_file} must contain a tokens array"
+        )
+
+    for index, token_entry in enumerate(token_entries):
+        if not isinstance(token_entry, dict):
+            raise AuthConfigError(
+                f"Static token file {token_file} entry {index} must be an 
object"
+            )
+        token_id = str(token_entry.get("token_id") or "").strip()
+        if not token_id:
+            raise AuthConfigError(
+                f"Static token file {token_file} entry {index} requires 
token_id"
+            )
+        raw_token = token_entry.get("token")
+        configured.append(
+            (
+                f"{token_file}:{token_id}",
+                raw_token,
+                _str_to_bool(token_entry.get("is_active", True)),
+            )
+        )
+    return configured
+
+
+def _validate_static_token_bootstrap(config: DorisConfig) -> None:
+    """Require at least one active high-entropy token when static auth is 
enabled."""
+    configured = _configured_static_tokens(config.security)
+    for setting, raw_token, _active in configured:
+        try:
+            validate_high_entropy_secret(raw_token, setting=setting)
+        except ValueError as exc:
+            raise AuthConfigError(str(exc)) from exc
+    if not any(active for _setting, _raw_token, active in configured):
+        raise AuthConfigError(
+            "Token authentication requires at least one active high-entropy 
credential. "
+            "Set TOKEN_<ID> or populate TOKEN_FILE_PATH before enabling it."
+        )
+
+
 def normalize_effective_auth_config(
     config: DorisConfig,
     requested_workers: int | None = None,
@@ -1367,6 +1438,21 @@ def normalize_effective_auth_config(
     if enable_doris_oauth_auth and enable_external_oauth_auth:
         raise AuthConfigError("Doris OAuth and external OAuth cannot be 
enabled together")
 
+    if enable_token_auth:
+        _validate_static_token_bootstrap(config)
+
+    if (
+        config.security.enable_http_token_management
+        and config.security.require_admin_auth
+    ):
+        try:
+            validate_high_entropy_secret(
+                config.security.token_management_admin_token,
+                setting="TOKEN_MANAGEMENT_ADMIN_TOKEN",
+            )
+        except ValueError as exc:
+            raise AuthConfigError(str(exc)) from exc
+
     transport = str(inputs.transport.value or "stdio")
     requested = int(inputs.workers.value if inputs.workers.value is not None 
else 1)
     effective_workers = multiprocessing.cpu_count() if requested == 0 else 
requested
diff --git a/doris_mcp_server/utils/db.py b/doris_mcp_server/utils/db.py
index 32d849c..ac06b4b 100644
--- a/doris_mcp_server/utils/db.py
+++ b/doris_mcp_server/utils/db.py
@@ -433,38 +433,6 @@ class DorisConnectionManager:
         return (not self._is_config_empty(self.original_db_config['host']) and
                 not self._is_config_empty(self.original_db_config['user']))
     
-    def _find_available_token_with_db_config(self) -> str:
-        """Find the first available token with database configuration
-        
-        Returns:
-            Raw token string if found, empty string if not found
-        """
-        if not self.token_manager:
-            return ""
-            
-        try:
-            for token_hash, token_info in self.token_manager._tokens.items():
-                if (token_info.database_config and 
-                    token_info.is_active and
-                    not self._is_config_empty(token_info.database_config.host) 
and
-                    not 
self._is_config_empty(token_info.database_config.user)):
-                    
-                    # We need to find the raw token from the hash
-                    # This is a bit tricky since we only store hashes
-                    # We'll need to use the admin token from tokens.json if it 
has db config
-                    if token_info.token_id == 'admin-token':
-                        # Try the known admin token
-                        return 'doris_admin_token_123456'
-                    elif 'tenant' in token_info.token_id:
-                        # For tenant tokens, we'll need a different approach
-                        # For now, skip these as we don't know the raw token
-                        continue
-                        
-            return ""
-        except Exception as e:
-            self.logger.error(f"Error finding available token: {e}")
-            return ""
-    
     def _get_token_hash(self, token: str) -> str:
         """Get hash of token for use as dictionary key"""
         import hashlib
@@ -1914,16 +1882,6 @@ class DorisConnectionManager:
                 if not self.pool:
                     self.logger.warning("Connection pool is not available, 
attempting recovery...")
                     
-                    # Try to use token-bound configuration if available
-                    if self.token_manager and not 
self._has_valid_global_config():
-                        available_token = 
self._find_available_token_with_db_config()
-                        if available_token:
-                            self.logger.info(f"Using token-bound configuration 
for pool creation: {available_token}")
-                            try:
-                                await self.configure_for_token(available_token)
-                            except Exception as e:
-                                self.logger.error(f"Failed to configure with 
token-bound config: {e}")
-                    
                     # Fallback to recovery
                     if not self.pool:
                         await self._recover_pool_with_lock()
diff --git a/doris_mcp_server/utils/secret_policy.py 
b/doris_mcp_server/utils/secret_policy.py
new file mode 100644
index 0000000..0bdc850
--- /dev/null
+++ b/doris_mcp_server/utils/secret_policy.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Shared policy for operator-provided authentication secrets."""
+
+MIN_SECRET_LENGTH = 32
+MIN_DISTINCT_CHARACTERS = 10
+
+_INSECURE_MARKERS = (
+    "123456",
+    "changeme",
+    "defaultsecret",
+    "exampletoken",
+    "password",
+    "yoursecret",
+    "yoursecure",
+)
+
+_RESERVED_TOKEN_ENV_NAMES = frozenset(
+    {
+        "TOKEN_EXPIRY",
+        "TOKEN_EXPIRY_HOURS",
+        "TOKEN_FILE_PATH",
+        "TOKEN_HASH_ALGORITHM",
+        "TOKEN_HOT_RELOAD",
+        "TOKEN_SECRET",
+    }
+)
+
+_RESERVED_TOKEN_ENV_PREFIXES = (
+    "TOKEN_HASH_",
+    "TOKEN_MANAGEMENT_",
+)
+
+
+def validate_high_entropy_secret(value: str, *, setting: str) -> str:
+    """Reject missing, short, repetitive, or placeholder authentication 
secrets."""
+    if not isinstance(value, str) or not value:
+        raise ValueError(f"{setting} is required")
+    if value != value.strip():
+        raise ValueError(f"{setting} must not contain leading or trailing 
whitespace")
+    if len(value) < MIN_SECRET_LENGTH:
+        raise ValueError(
+            f"{setting} must be at least {MIN_SECRET_LENGTH} characters; "
+            "generate it with a cryptographically secure random generator"
+        )
+    if value.startswith("<") or value.endswith(">"):
+        raise ValueError(f"{setting} must not be a placeholder")
+    compact = "".join(
+        character for character in value.casefold() if character.isalnum()
+    )
+    if any(marker in compact for marker in _INSECURE_MARKERS):
+        raise ValueError(
+            f"{setting} must not contain a known weak or placeholder value"
+        )
+    if len(set(value)) < MIN_DISTINCT_CHARACTERS:
+        raise ValueError(
+            f"{setting} must contain at least {MIN_DISTINCT_CHARACTERS} 
distinct characters"
+        )
+    return value
+
+
+def is_static_token_environment_variable(name: str) -> bool:
+    """Return whether an environment variable defines a static bearer token."""
+    if not name.startswith("TOKEN_"):
+        return False
+    if name in _RESERVED_TOKEN_ENV_NAMES:
+        return False
+    if name.startswith(_RESERVED_TOKEN_ENV_PREFIXES):
+        return False
+    return not name.endswith(("_DESCRIPTION", "_EXPIRES_HOURS"))
diff --git a/test/security/test_effective_auth_config.py 
b/test/security/test_effective_auth_config.py
index c2f0b2c..e3b229c 100644
--- a/test/security/test_effective_auth_config.py
+++ b/test/security/test_effective_auth_config.py
@@ -9,6 +9,8 @@ from doris_mcp_server.utils.config import (
 )
 from doris_mcp_server.utils.security import AuthenticationProvider
 
+STATIC_TOKEN = "V4nK8qR2mT7xP5cL9sD3hF6jY1uB0eG4iW8aN2zQ"
+
 
 def test_default_auth_methods_remain_disabled():
     config = DorisConfig()
@@ -35,10 +37,12 @@ def 
test_explicit_oauth_false_conflicts_with_oauth_enabled_true():
         normalize_effective_auth_config(config)
 
 
-def test_legacy_auth_type_only_applies_when_explicit():
+def test_legacy_auth_type_only_applies_when_explicit(tmp_path, monkeypatch):
     config = DorisConfig()
+    config.security.token_file_path = str(tmp_path / "tokens.json")
     config.security.auth_type = "token"
     _mark_source(config, "auth_type", "env")
+    monkeypatch.setenv("TOKEN_TEST", STATIC_TOKEN)
 
     effective = normalize_effective_auth_config(config)
 
diff --git a/test/security/test_static_token_bootstrap.py 
b/test/security/test_static_token_bootstrap.py
new file mode 100644
index 0000000..4cab88a
--- /dev/null
+++ b/test/security/test_static_token_bootstrap.py
@@ -0,0 +1,171 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import json
+import os
+from pathlib import Path
+
+import pytest
+
+from doris_mcp_server.auth.token_manager import TokenManager
+from doris_mcp_server.utils.config import (
+    AuthConfigError,
+    DorisConfig,
+    _mark_source,
+    normalize_effective_auth_config,
+)
+from doris_mcp_server.utils.secret_policy import (
+    is_static_token_environment_variable,
+)
+
+STATIC_TOKEN = "V4nK8qR2mT7xP5cL9sD3hF6jY1uB0eG4iW8aN2zQ"
+MANAGEMENT_TOKEN = "Q7cM2vR9kL4xT8pD5sF1hJ6uB3eG0iW9aN2zY8qP"
+
+
+def _config(tmp_path: Path) -> DorisConfig:
+    config = DorisConfig()
+    config.security.token_file_path = str(tmp_path / "tokens.json")
+    return config
+
+
+def _clear_static_token_environment(monkeypatch: pytest.MonkeyPatch) -> None:
+    for name in list(os.environ):
+        if is_static_token_environment_variable(name):
+            monkeypatch.delenv(name, raising=False)
+
+
+def test_repository_token_template_contains_no_credentials():
+    token_file = Path(__file__).parents[2] / "tokens.json"
+
+    token_data = json.loads(token_file.read_text(encoding="utf-8"))
+
+    assert token_data["tokens"] == []
+    assert "No usable credential is shipped" in token_data["notes"][0]
+
+
+def test_legacy_token_secret_has_no_default():
+    assert DorisConfig().security.token_secret == ""
+
+
+def test_static_auth_rejects_missing_active_credentials(tmp_path, monkeypatch):
+    _clear_static_token_environment(monkeypatch)
+    config = _config(tmp_path)
+    config.security.enable_token_auth = True
+    _mark_source(config, "enable_token_auth", "env")
+
+    with pytest.raises(AuthConfigError, match="at least one active 
high-entropy"):
+        normalize_effective_auth_config(config)
+
+
+def test_static_auth_rejects_weak_environment_token(tmp_path, monkeypatch):
+    _clear_static_token_environment(monkeypatch)
+    config = _config(tmp_path)
+    config.security.enable_token_auth = True
+    _mark_source(config, "enable_token_auth", "env")
+    monkeypatch.setenv("TOKEN_ADMIN", "short-token")
+
+    with pytest.raises(AuthConfigError, match="at least 32 characters"):
+        normalize_effective_auth_config(config)
+
+
+def test_management_settings_are_not_loaded_as_static_tokens(tmp_path, 
monkeypatch):
+    _clear_static_token_environment(monkeypatch)
+    config = _config(tmp_path)
+    config.security.enable_token_auth = True
+    _mark_source(config, "enable_token_auth", "env")
+    monkeypatch.setenv("TOKEN_MANAGEMENT_ADMIN_TOKEN", MANAGEMENT_TOKEN)
+    monkeypatch.setenv("TOKEN_MANAGEMENT_ALLOWED_IPS", "127.0.0.1")
+
+    with pytest.raises(AuthConfigError, match="at least one active 
high-entropy"):
+        normalize_effective_auth_config(config)
+
+
[email protected]
+async def test_strong_environment_token_bootstraps_static_auth(tmp_path, 
monkeypatch):
+    _clear_static_token_environment(monkeypatch)
+    config = _config(tmp_path)
+    config.security.enable_token_auth = True
+    _mark_source(config, "enable_token_auth", "env")
+    monkeypatch.setenv("TOKEN_ADMIN", STATIC_TOKEN)
+
+    normalize_effective_auth_config(config)
+    manager = TokenManager(config)
+    try:
+        result = await manager.validate_token(STATIC_TOKEN)
+        assert result.is_valid is True
+        assert result.token_info.token_id == "admin"
+        assert len(manager._tokens) == 1
+    finally:
+        manager.stop_hot_reload()
+
+
[email protected]
+async def test_manager_does_not_create_credentials_when_auth_is_disabled(
+    tmp_path,
+    monkeypatch,
+):
+    _clear_static_token_environment(monkeypatch)
+    manager = TokenManager(_config(tmp_path))
+    try:
+        assert manager._tokens == {}
+        assert manager._token_ids == {}
+    finally:
+        manager.stop_hot_reload()
+
+
[email protected]
+async def test_custom_static_token_must_follow_secret_policy(tmp_path, 
monkeypatch):
+    _clear_static_token_environment(monkeypatch)
+    manager = TokenManager(_config(tmp_path))
+    try:
+        with pytest.raises(ValueError, match="at least 32 characters"):
+            await manager.create_token("weak", custom_token="short-token")
+
+        generated = await manager.create_token("generated")
+        assert len(generated) >= 32
+        assert (await manager.validate_token(generated)).is_valid is True
+    finally:
+        manager.stop_hot_reload()
+
+
[email protected](
+    ("admin_token", "error"),
+    [
+        ("", "is required"),
+        ("short-token", "at least 32 characters"),
+        ("a" * 40, "distinct characters"),
+    ],
+)
+def test_http_token_management_rejects_weak_admin_secret(admin_token, error):
+    config = DorisConfig()
+    config.security.enable_http_token_management = True
+    config.security.require_admin_auth = True
+    config.security.token_management_admin_token = admin_token
+
+    with pytest.raises(AuthConfigError, match=error):
+        normalize_effective_auth_config(config)
+
+
+def test_http_token_management_accepts_high_entropy_admin_secret():
+    config = DorisConfig()
+    config.security.enable_http_token_management = True
+    config.security.require_admin_auth = True
+    config.security.token_management_admin_token = MANAGEMENT_TOKEN
+
+    effective = normalize_effective_auth_config(config)
+
+    assert effective.auth_methods == ()
diff --git a/test/security/test_token_management_auth.py 
b/test/security/test_token_management_auth.py
index 79ef623..287c94e 100644
--- a/test/security/test_token_management_auth.py
+++ b/test/security/test_token_management_auth.py
@@ -27,7 +27,7 @@ from doris_mcp_server.auth.token_handlers import TokenHandlers
 from doris_mcp_server.auth.token_security_middleware import 
TokenSecurityMiddleware
 from doris_mcp_server.utils.config import DorisConfig
 
-ADMIN_TOKEN = "test-admin-token"
+ADMIN_TOKEN = "J8pR4mX2vN7qL5sT9kW3cF6hY1uD8aB0eG4iC2oP"
 
 
 def _config() -> DorisConfig:
diff --git a/tokens.json b/tokens.json
index 878e2f1..aae0b8f 100644
--- a/tokens.json
+++ b/tokens.json
@@ -1,64 +1,10 @@
 {
   "version": "1.0",
-  "description": "Doris MCP Server Token configuration file",
-  "created_at": "2025-09-01T00:00:00Z",
-  "tokens": [
-    {
-      "token_id": "admin-token",
-      "token": "doris_admin_token_123456",
-      "description": "Doris admin API access token",
-      "expires_hours": null,
-      "is_active": true,
-      "database_config": {
-        "host": "127.0.0.1",
-        "port": 9030,
-        "user": "root",
-        "password": "",
-        "database": "information_schema",
-        "charset": "UTF8",
-        "fe_http_port": 8030
-      }
-    },
-    {
-      "token_id": "analyst-token",
-      "token": "doris_analyst_token_123456",
-      "description": "Doris analyst API access token",
-      "expires_hours": 8760,
-      "is_active": true,
-      "database_config": {
-        "host": "127.0.0.1",
-        "port": 9030,
-        "user": "root",
-        "password": "",
-        "database": "information_schema",
-        "charset": "UTF8",
-        "fe_http_port": 8030
-      }
-    },
-    {
-      "token_id": "readonly-token",
-      "token": "doris_readonly_token_123456",
-      "description": "Doris readonly API access token",
-      "expires_hours": 4320,
-      "is_active": true,
-      "database_config": {
-        "host": "127.0.0.1",
-        "port": 9030,
-        "user": "root",
-        "password": "",
-        "database": "information_schema",
-        "charset": "UTF8",
-        "fe_http_port": 8030
-      }
-    }
-  ],
+  "description": "Credential-free Doris MCP Server token configuration 
template",
+  "tokens": [],
   "notes": [
-    "The admin_token, analyst_token, readonly_token is default token,Please 
change the token before using in production!",
-    "The token_id is the key of the token,Please use the token_id to identify 
the token",
-    "The token is the value of the token,Please use the token to identify the 
token",
-    "The description is the description of the token,Please use the 
description to identify the token",
-    "The expires_hours is the expires hours of the token,Please use the 
expires_hours to identify the token",
-    "The is_active is the is active of the token,Please use the is_active to 
identify the token",
-    "The token_id, token, description, expires_hours, is_active is the 
metadata of the token,Please use the metadata to identify the token"
+    "No usable credential is shipped with the server.",
+    "Before enabling static token authentication, configure at least one 
active token with 32 or more characters generated by a cryptographically secure 
random generator.",
+    "Do not commit deployment credentials to source control."
   ]
-}
\ No newline at end of file
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to