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:
viettranx committed 2026-03-24 09:59:07 +07:00
1 parent aadc4d6498
commit c43a8f125b
3 files changed
+21 -7

No files matched your search

+1
View File
@@ -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.
+8
View File
@@ -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)
+12 -7
View File
@@ -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