* fix(agents): enforce visibility guard after sessionId resolution in session_status
When a sessionId (rather than an explicit agent key) is passed to the
session_status tool, the sessionId resolution block rewrites
requestedKeyRaw to an explicit "agent:..." key. The subsequent
visibility guard check at line 375 tested
`!requestedKeyRaw.startsWith("agent:")`, which was now always false
after resolution — skipping the visibility check entirely.
This meant a sandboxed agent could bypass visibility restrictions by
providing a sessionId instead of an explicit session key.
Fix: use the original `isExplicitAgentKey` flag (captured before
resolution) instead of re-checking the dynamic requestedKeyRaw.
This ensures the visibility guard runs for sessionId inputs while
still skipping the redundant check for inputs that were already
validated at the earlier explicit-key check (lines 281-286).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: cover session status sessionId guard
* test: align parent sessionId guard coverage
---------
Co-authored-by: Kevin Sheng <shenghuikevin@github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(extensions): route fetch calls through fetchWithSsrFGuard
Replace raw fetch() with fetchWithSsrFGuard in BlueBubbles, Mattermost,
Nextcloud Talk, and Thread Ownership extensions so outbound requests go
through the shared DNS-pinning and network-policy layer.
BlueBubbles: thread allowPrivateNetwork from account config through all
fetch call sites (send, chat, reactions, history, probe, attachments,
multipart). Add _setFetchGuardForTesting hook for test overrides.
Mattermost: add guardedFetchImpl wrapper in createMattermostClient that
buffers the response body before releasing the dispatcher. Handle
null-body status codes (204/304).
Nextcloud Talk: wrap both sendMessage and sendReaction with
fetchWithSsrFGuard and try/finally release.
Thread Ownership: add fetchWithSsrFGuard and ssrfPolicyFromAllowPrivateNetwork
to the plugin SDK surface; use allowPrivateNetwork:true for the
Docker-internal forwarder.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(extensions): improve null-body handling and test harness cleanup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(bluebubbles): default to strict SSRF policy when allowPrivateNetwork is unset
Callers that omit allowPrivateNetwork previously got undefined policy,
which caused blueBubblesFetchWithTimeout to fall through to raw fetch
and bypass the SSRF guard entirely.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(bluebubbles): thread allowPrivateNetwork through action and monitor call sites
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mattermost,nextcloud-talk): add allowPrivateNetwork config for self-hosted/LAN deployments
* fix: regenerate config docs baseline for new allowPrivateNetwork fields
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove Qwen OAuth integration (qwen-portal-auth)
Qwen OAuth via portal.qwen.ai is being deprecated by the Qwen team due
to traffic impact on their primary Qwen Code user base. Users should
migrate to the officially supported Model Studio (Alibaba Cloud Coding
Plan) provider instead.
Ref: https://github.com/openclaw/openclaw/issues/49557
- Delete extensions/qwen-portal-auth/ plugin entirely
- Remove qwen-portal from onboarding auth choices, provider aliases,
auto-enable list, bundled plugin defaults, and pricing cache
- Remove Qwen CLI credential sync (external-cli-sync, cli-credentials)
- Remove QWEN_OAUTH_MARKER from model auth markers
- Update docs/providers/qwen.md to redirect to Model Studio
- Update model-providers docs (EN + zh-CN) to remove Qwen OAuth section
- Regenerate config and plugin-sdk baselines
- Update all affected tests
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* Clean up residual qwen-portal references after OAuth removal
* Add migration hint for deprecated qwen-portal OAuth provider
* fix: finish qwen oauth removal follow-up
---------
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
* Docs: rename modelstudio.md to qwen_modelstudio.md, add Standard API endpoints
* refine docs
* Docs: fix broken link in providers/index.md after modelstudio rename
* Docs: add redirect from /providers/modelstudio to /providers/qwen_modelstudio
* Docs: adjust the order in index.md
* docs: rename modelstudio to qwen_modelstudio, add Standard API endpoints (#54407) (thanks @wenmengzhou)
---------
Co-authored-by: George Zhang <georgezhangtj97@gmail.com>
* Microsoft Foundry: add native provider
* Microsoft Foundry: tighten review fixes
* Microsoft Foundry: enable by default
* Microsoft Foundry: stabilize API routing
* msteams: add pin/unpin, list-pins, and read message actions
Wire up Graph API endpoints for message read, pin, unpin, and list-pins
in the MS Teams extension, following the same patterns as edit/delete.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: address PR review comments for pin/unpin/read actions
- Handle 204 No Content in postGraphJson (Graph mutations may return empty body)
- Strip conversation:/user: prefixes in resolveConversationPath to avoid Graph 404s
- Remove dead variable in channel pin branch
- Rename unpin param from messageId to pinnedMessageId for semantic clarity
- Accept both pinnedMessageId and messageId in unpin action handler for compat
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: resolve user targets + add User-Agent to Graph helpers
- Resolve user:<aadId> targets to actual conversation IDs via conversation
store before Graph API calls (fixes 404 for DM-context actions)
- Add User-Agent header to postGraphJson/deleteGraphRequest for consistency
with fetchGraphJson after rebase onto main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: resolve DM targets to Graph chat IDs + expose pin IDs
- Prefer cached graphChatId over Bot Framework conversation IDs for user
targets; throw descriptive error when no Graph-compatible ID is available
- Add `id` field to list-pins rows so default formatters surface the pinned
resource ID needed for the unpin flow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: add react and reactions (list) message actions
* msteams: add search message action via Graph API
* msteams: fix search query injection, add ConsistencyLevel header, use manual query string
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: fetch thread history via Graph API for channel replies
* msteams: address PR #51643 review feedback
- Wrap resolveTeamGroupId Graph call in try/catch, fall back to raw
conversationTeamId when Team.ReadBasic.All permission is missing
- Remove dead fetchChatMessages function (exported but never called)
- Add JSDoc documenting oldest-50-replies Graph API limitation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: address thread history PR review comments
* msteams: only cache team group IDs on successful Graph lookup
Avoid caching raw conversationTeamId as a Graph team GUID when the
/teams/{id} lookup fails — the raw ID may be a Bot Framework conversation
key, not a valid GUID, causing silent thread-history failures for the
entire cache TTL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass agentId in CLI message command to enable session transcript writes
The CLI `openclaw message send` command was not passing `agentId` to
`runMessageAction()`, causing the outbound session route resolution to
be skipped (it's gated on `agentId && !dryRun`). Without a route, the
`mirror` object is never constructed, and `appendAssistantMessageToSessionTranscript()`
is never called.
This fix resolves the agent ID from the config (defaulting to "main")
and passes it through, enabling transcript mirroring for all channels
when using the CLI.
Closes#54186
* fix: format message.ts with oxfmt
* fix: use resolveDefaultAgentId instead of cfg.agent
* fix: restore CLI message transcript mirroring (#54187) (thanks @KevInTheCloud5617)
---------
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* daemon: tighten systemd duplicate gateway detection (#15849)
* fix three issues from PR review
* fix windows unit tests due to posix/windows path differences
* ensure line continuations are handled in systemd units
* fix misleading test name
* attempt fix windows test due to fs path separator
* fix system_dir separator, fix platform side-effect
* change approach for mocking systemd filesystem test
* normalize systemd paths to linux style
* revert to vers that didnt impact win32 tests
* back out all systemd inspect tests
* change test approach to avoid other tests issues
* fix: tighten systemd duplicate gateway detection (#45328) (thanks @gregretkowski)
---------
Co-authored-by: Ayaan Zaidi <hi@obviy.us>