mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-15 08:17:09 +00:00
fix(security): harden MCP bridge auth and add startup security warnings (#306)
MCP bridge now returns 403 when no gateway token is configured instead of serving tools without authentication. Startup warnings added for default Postgres password and open CORS configuration.
This commit is contained in:
1 parent
aadc4d6498
commit
c43a8f125b
3 files changed
+21
-7
No files matched your search
@@ -7,6 +7,7 @@
|
||||
# --- Gateway (required) ---
|
||||
GOCLAW_GATEWAY_TOKEN=
|
||||
GOCLAW_ENCRYPTION_KEY=
|
||||
POSTGRES_PASSWORD=
|
||||
|
||||
# --- Database (only for non-Docker deployments) ---
|
||||
# Docker Compose auto-builds this from POSTGRES_USER/PASSWORD/DB.
|
||||
|
||||
@@ -1059,6 +1059,14 @@ func runGateway() {
|
||||
slog.Info("Tailscale enabled. Consider setting GOCLAW_HOST=127.0.0.1 for localhost-only + Tailscale access")
|
||||
}
|
||||
|
||||
// Security warnings
|
||||
if strings.Contains(cfg.Database.PostgresDSN, ":goclaw@") {
|
||||
slog.Warn("security.default_db_password: using default Postgres password — run ./prepare-env.sh to generate a strong one")
|
||||
}
|
||||
if len(cfg.Gateway.AllowedOrigins) == 0 {
|
||||
slog.Warn("security.cors_open: no allowed_origins configured — all WebSocket origins accepted. Set gateway.allowed_origins for production")
|
||||
}
|
||||
|
||||
if err := server.Start(ctx); err != nil {
|
||||
slog.Error("gateway error", "error", err)
|
||||
os.Exit(1)
|
||||
|
||||
@@ -312,17 +312,22 @@ func (s *Server) BuildMux() *http.ServeMux {
|
||||
|
||||
// MCP bridge: expose GoClaw tools to Claude CLI via streamable-http.
|
||||
// Only listens on localhost (CLI runs on the same machine).
|
||||
// Protected by gateway token when configured.
|
||||
// Agent context (X-Agent-ID, X-User-ID) is injected from request headers.
|
||||
// Protected by gateway token; disabled when no token is configured to
|
||||
// prevent unauthenticated tool invocations if port is exposed.
|
||||
if s.tools != nil {
|
||||
bridgeHandler := mcpbridge.NewBridgeServer(s.tools, "1.0.0", s.msgBus)
|
||||
var handler http.Handler = bridgeContextMiddleware(s.cfg.Gateway.Token, bridgeHandler)
|
||||
if s.cfg.Gateway.Token != "" {
|
||||
handler = tokenAuthMiddleware(s.cfg.Gateway.Token, handler)
|
||||
bridgeHandler := mcpbridge.NewBridgeServer(s.tools, "1.0.0", s.msgBus)
|
||||
handler := tokenAuthMiddleware(s.cfg.Gateway.Token,
|
||||
bridgeContextMiddleware(s.cfg.Gateway.Token, bridgeHandler))
|
||||
mux.Handle("/mcp/bridge", handler)
|
||||
} else {
|
||||
slog.Warn("security.mcp_bridge: no gateway token configured, MCP bridge tools are unauthenticated")
|
||||
slog.Warn("security.mcp_bridge_disabled: no gateway token configured, MCP bridge is disabled")
|
||||
mux.HandleFunc("/mcp/bridge", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
_, _ = w.Write([]byte(`{"error":"mcp bridge disabled: set GOCLAW_GATEWAY_TOKEN to enable"}`))
|
||||
})
|
||||
}
|
||||
mux.Handle("/mcp/bridge", handler)
|
||||
}
|
||||
|
||||
s.mux = mux
|
||||
|
||||
Reference in new issue
Block a user