diff --git a/internal/api/router.go b/internal/api/router.go index 48f9f58dd..c9c13ba12 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -1902,6 +1902,18 @@ func (r *Router) handleVerifyTemperatureSSH(w http.ResponseWriter, req *http.Req return } + // Check admin privileges for proxy auth users + if r.config.ProxyAuthSecret != "" { + if valid, username, isAdmin := CheckProxyAuth(r.config, req); valid && !isAdmin { + log.Warn(). + Str("ip", GetClientIP(req)). + Str("username", username). + Msg("Non-admin user attempted verify-temperature-ssh") + http.Error(w, "Admin privileges required", http.StatusForbidden) + return + } + } + // Require settings:write scope for API tokens (SSH probes are a privileged operation) if !ensureScope(w, req, config.ScopeSettingsWrite) { return @@ -1943,6 +1955,18 @@ func (r *Router) handleSSHConfig(w http.ResponseWriter, req *http.Request) { return } + // Check admin privileges for proxy auth users + if r.config.ProxyAuthSecret != "" { + if valid, username, isAdmin := CheckProxyAuth(r.config, req); valid && !isAdmin { + log.Warn(). + Str("ip", GetClientIP(req)). + Str("username", username). + Msg("Non-admin user attempted ssh-config update") + http.Error(w, "Admin privileges required", http.StatusForbidden) + return + } + } + // Require settings:write scope for API tokens (SSH config writes are a privileged operation) if !ensureScope(w, req, config.ScopeSettingsWrite) { return diff --git a/internal/api/security_regression_test.go b/internal/api/security_regression_test.go index efa785094..e3e0bc1f3 100644 --- a/internal/api/security_regression_test.go +++ b/internal/api/security_regression_test.go @@ -1948,6 +1948,8 @@ func TestProxyAuthNonAdminDeniedAdminEndpoints(t *testing.T) { {method: http.MethodPost, path: "/api/security/reset-lockout", body: `{}`}, {method: http.MethodPost, path: "/api/security/apply-restart", body: `{}`}, {method: http.MethodPost, path: "/api/security/oidc", body: `{}`}, + {method: http.MethodPost, path: "/api/system/verify-temperature-ssh", body: `{}`}, + {method: http.MethodPost, path: "/api/system/ssh-config", body: `{}`}, {method: http.MethodGet, path: "/api/ai/debug/context", body: ""}, {method: http.MethodPost, path: "/api/ai/execute", body: `{}`}, {method: http.MethodPost, path: "/api/ai/execute/stream", body: `{}`},