diff --git a/control-plane/internal/server/middleware/auth.go b/control-plane/internal/server/middleware/auth.go index 370b617c..b4d04b14 100644 --- a/control-plane/internal/server/middleware/auth.go +++ b/control-plane/internal/server/middleware/auth.go @@ -109,13 +109,21 @@ func APIKeyAuth(config AuthConfig) gin.HandlerFunc { } // AdminTokenAuth enforces a separate admin token for admin routes. -// If adminToken is empty, the middleware is a no-op (falls back to global API key auth). // Admin tokens must be sent via the X-Admin-Token header only (not Bearer) to avoid // collision with the API key Bearer token namespace. +// Fixes #425: admin routes are now fail-closed when adminToken is unset (previously +// the middleware was a no-op, silently falling back to API key auth or no auth at all). func AdminTokenAuth(adminToken string) gin.HandlerFunc { return func(c *gin.Context) { if adminToken == "" { - c.Next() + // Fail closed: admin routes are inaccessible if admin token is not configured. + // This prevents accidental exposure of admin routes when the token is misconfigured. + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ + "error": "configuration_error", + "message": "admin token is not configured on this server. " + + "Set AGENTFIELD_AUTHORIZATION_ADMIN_TOKEN for production use. " + + "See: https://github.com/Agent-Field/agentfield/issues/425", + }) return } diff --git a/control-plane/internal/server/server.go b/control-plane/internal/server/server.go index 0e36db76..a4637950 100644 --- a/control-plane/internal/server/server.go +++ b/control-plane/internal/server/server.go @@ -978,6 +978,14 @@ func (s *AgentFieldServer) setupRoutes() { })) if s.config.API.Auth.APIKey != "" { logger.Logger.Info().Msg("🔐 API key authentication enabled") + } else { + // SECURITY WARNING: middleware is a no-op when API key is empty (issue #424) + // All non-public routes become accessible without credentials. + // Only public routes (/api/v1/agentic/kb/*, /health, /metrics) are safe without auth. + logger.Logger.Error().Msg("⚠️ SECURITY WARNING: No API key configured (AGENTFIELD_API_AUTH_APIKEY is empty). " + + "API key authentication is disabled — all non-public routes are unprotected. " + + "Set AGENTFIELD_API_AUTH_APIKEY for production deployments. " + + "See: https://github.com/Agent-Field/agentfield/issues/424") } // DID authentication middleware (applied globally, but only validates when headers present)