Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/OpenClaw.Shared/OpenClawGatewayClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,8 @@ private void HandleToolEvent(JsonElement payload, string sessionKey, bool isMain

private void HandleChatEvent(JsonElement root)
{
_logger.Debug($"Chat event received: {root.GetRawText().Substring(0, Math.Min(200, root.GetRawText().Length))}");
var rawText = root.GetRawText();
_logger.Debug($"Chat event received: {rawText.Substring(0, Math.Min(200, rawText.Length))}");

if (!root.TryGetProperty("payload", out var payload)) return;

Expand Down
31 changes: 18 additions & 13 deletions src/OpenClaw.Tray.WinUI/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ public partial class App : Application
private DateTime _lastCheckTime = DateTime.Now;
private DateTime _lastUsageActivityLogUtc = DateTime.MinValue;

// FrozenDictionary for O(1) case-insensitive notification type β†’ setting lookup β€” no per-call allocation.
private static readonly System.Collections.Frozen.FrozenDictionary<string, Func<SettingsManager, bool>> s_notifTypeMap =
new Dictionary<string, Func<SettingsManager, bool>>(StringComparer.OrdinalIgnoreCase)
{
["health"] = s => s.NotifyHealth,
["urgent"] = s => s.NotifyUrgent,
["reminder"] = s => s.NotifyReminder,
["email"] = s => s.NotifyEmail,
["calendar"] = s => s.NotifyCalendar,
["build"] = s => s.NotifyBuild,
["stock"] = s => s.NotifyStock,
["info"] = s => s.NotifyInfo,
["error"] = s => s.NotifyUrgent, // errors follow urgent setting
}.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase);

// Session-aware activity tracking
private readonly Dictionary<string, AgentActivity> _sessionActivities = new();
private string? _displayedSessionKey;
Expand Down Expand Up @@ -1459,19 +1474,9 @@ private bool ShouldShowNotification(OpenClawNotification notification)
if (notification.IsChat && !_settings.NotifyChatResponses)
return false;

return notification.Type?.ToLowerInvariant() switch
{
"health" => _settings.NotifyHealth,
"urgent" => _settings.NotifyUrgent,
"reminder" => _settings.NotifyReminder,
"email" => _settings.NotifyEmail,
"calendar" => _settings.NotifyCalendar,
"build" => _settings.NotifyBuild,
"stock" => _settings.NotifyStock,
"info" => _settings.NotifyInfo,
"error" => _settings.NotifyUrgent, // errors follow urgent setting
_ => true
};
var type = notification.Type;
if (type == null) return true;
return s_notifTypeMap.TryGetValue(type, out var selector) ? selector(_settings) : true;
}

#endregion
Expand Down
16 changes: 10 additions & 6 deletions src/OpenClaw.Tray.WinUI/Windows/CanvasWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ public sealed partial class CanvasWindow : WindowEx
private readonly TaskCompletionSource<bool> _webViewReadyTcs = new(TaskCreationOptions.RunContinuationsAsynchronously);
private TaskCompletionSource<bool>? _navigationTcs;

// HTML sanitization β€” block embedded iframes/objects/embeds/applets
private static readonly Regex s_sanitizeBlock = new(
@"<\s*(iframe|object|embed|applet)\b[^>]*>.*?<\s*/\s*\1\s*>",
RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
private static readonly Regex s_sanitizeSelfClose = new(
@"<\s*(iframe|object|embed|applet)\b[^>]*/?\s*>",
RegexOptions.IgnoreCase | RegexOptions.Compiled);

// URL validation - block dangerous schemes and private networks (IPv4 + IPv6)
private static readonly Regex DangerousUrlPattern = new(
@"^(file|javascript|data|vbscript):|" + // Dangerous schemes
Expand Down Expand Up @@ -247,13 +255,9 @@ public void LoadHtml(string html)
private static string SanitizeHtml(string html)
{
// Remove <iframe>, <object>, <embed>, <applet> tags and their content
html = System.Text.RegularExpressions.Regex.Replace(
html, @"<\s*(iframe|object|embed|applet)\b[^>]*>.*?<\s*/\s*\1\s*>",
"<!-- blocked -->", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
html = s_sanitizeBlock.Replace(html, "<!-- blocked -->");
// Remove self-closing variants
html = System.Text.RegularExpressions.Regex.Replace(
html, @"<\s*(iframe|object|embed|applet)\b[^>]*/?\s*>",
"<!-- blocked -->", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
html = s_sanitizeSelfClose.Replace(html, "<!-- blocked -->");
return html;
}

Expand Down