* feat(bluebubbles): auto-strip markdown from outbound messages (#7402)
* fix(security): add timeout to webhook body reading (#6762)
Adds 30-second timeout to readBody() in voice-call, bluebubbles, and nostr
webhook handlers. Prevents Slow-Loris DoS (CWE-400, CVSS 7.5).
Merged with existing maxBytes protection in voice-call.
* fix(security): unify Error objects and lint fixes in webhook timeouts (#6762)
* fix: prevent plugins from auto-enabling without user consent (#3961)
Changes default plugin enabled state from true to false in enablePluginEntry().
Preserves existing enabled:true values. Fixes#3932.
* fix: apply hierarchical mediaMaxMb config to all channels (#8749)
Generalizes resolveAttachmentMaxBytes() to use account → channel → global
config resolution for all channels, not just BlueBubbles. Fixes#7847.
* fix(bluebubbles): sanitize attachment filenames against header injection (#10333)
Strip ", \r, \n, and \\ from filenames after path.basename() to prevent
multipart Content-Disposition header injection (CWE-93, CVSS 5.4).
Also adds sanitization to setGroupIconBlueBubbles which had zero filename
sanitization.
* fix(lint): exclude extensions/ from Oxlint preflight check (#9313)
Extensions use PluginRuntime|null patterns that trigger
no-redundant-type-constituents because PluginRuntime resolves to any.
Excluding extensions/ from Oxlint unblocks user upgrades.
Re-applies the approach from closed PR #10087.
* fix(bluebubbles): add tempGuid to createNewChatWithMessage payload (#7745)
Non-Private-API mode (AppleScript) requires tempGuid in send payloads.
The main sendMessageBlueBubbles already had it, but createNewChatWithMessage
was missing it, causing 400 errors for new chat creation without Private API.
* fix: send stop-typing signal when run ends with NO_REPLY (#8785)
Adds onCleanup callback to the typing controller that fires when the
controller is cleaned up while typing was active (e.g., after NO_REPLY).
Channels using createTypingCallbacks automatically get stop-typing on
cleanup. This prevents the typing indicator from lingering in group chats
when the agent decides not to reply.
* fix(telegram): deduplicate skill commands in multi-agent setup (#5717)
Two fixes:
1. Skip duplicate workspace dirs when listing skill commands across agents.
Multiple agents sharing the same workspace would produce duplicate commands
with _2, _3 suffixes.
2. Clear stale commands via deleteMyCommands before registering new ones.
Commands from deleted skills now get cleaned up on restart.
* fix: add size limits to unbounded in-memory caches (#4948)
Adds max-size caps with oldest-entry eviction to prevent OOM in
long-running deployments:
- BlueBubbles serverInfoCache: 64 entries (already has TTL)
- Google Chat authCache: 32 entries
- Matrix directRoomCache: 1024 entries
- Discord presenceCache: 5000 entries per account
* fix: address review concerns (#11093)
- Chain deleteMyCommands → setMyCommands to prevent race condition (#5717)
- Rename enablePluginEntry to registerPluginEntry (now sets enabled: false)
- Add Slow-Loris timeout test for readJsonBody (#6023)
Previously, startTypingLoop would return early if the typing timer was
already running, which meant the TTL would never get refreshed during
long tool executions. This caused the typing indicator to stop after
2 minutes even if tools were still running.
Now we refresh the TTL at the start of startTypingLoop, before the
early-return checks. This keeps typing alive during long operations.