fix(msteams): fetch OneDrive/SharePoint shared media via Graph shares endpoint (#55383)#63942
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 526cb5943b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!host) { | ||
| return false; | ||
| } | ||
| return GRAPH_SHARED_LINK_HOST_SUFFIXES.some((suffix) => host === suffix || host.endsWith(suffix)); |
There was a problem hiding this comment.
Tighten shared-link host suffix matching
isGraphSharedLinkUrl uses host.endsWith(suffix) for every suffix, so entries without a leading dot (onedrive.com, 1drv.ms) also match unrelated hostnames like notonedrive.com and evil1drv.ms. In resolveDownloadCandidate this misclassification rewrites those URLs to graph.microsoft.com/shares/..., which bypasses the original attachment-host allowlist check (the rewritten Graph URL is allowed) and triggers Graph-token fetch attempts for links that should be rejected. Matching should require a label boundary (for example host === suffix || host.endsWith('.' + suffix)) for bare-domain suffixes.
Useful? React with 👍 / 👎.
Greptile SummaryThis PR fixes OneDrive/SharePoint shared-file downloads in Teams 1:1 DMs by rewriting the attachment
Confidence Score: 4/5Safe to merge for the 1:1 DM fix, but onedrive.live.com attachments in group chats will still silently fail due to the allowlist gap. The 1:1 DM fix is correct and well-tested. One P1 gap:
|
| const GRAPH_SHARED_LINK_HOST_SUFFIXES = [ | ||
| ".sharepoint.com", | ||
| ".sharepoint.us", | ||
| ".sharepoint.de", | ||
| ".sharepoint.cn", | ||
| ".sharepoint-df.com", | ||
| "1drv.ms", | ||
| "onedrive.live.com", | ||
| "onedrive.com", | ||
| ] as const; |
There was a problem hiding this comment.
onedrive.live.com missing from DEFAULT_MEDIA_HOST_ALLOWLIST
onedrive.live.com is added to GRAPH_SHARED_LINK_HOST_SUFFIXES here, but it does not appear in DEFAULT_MEDIA_HOST_ALLOWLIST (neither as an exact entry nor matched by the "onedrive.com" suffix, since "onedrive.live.com".endsWith("onedrive.com") is false).
In graph.ts (the group-chat path), isUrlAllowed(shareUrl, policy.allowHosts) is checked against the original contentUrl before building the sharesUrl. Because onedrive.live.com is not in the allowlist, that guard silently skips every onedrive.live.com reference attachment in group chats. The download.ts (1:1 DM) path is unaffected because resolveDownloadCandidate rewrites the URL to graph.microsoft.com before the allowlist check.
Adding onedrive.live.com to GRAPH_SHARED_LINK_HOST_SUFFIXES implies it is fully handled, but the group-chat path will drop these attachments without error. The fix requires also adding "onedrive.live.com" to DEFAULT_MEDIA_HOST_ALLOWLIST (around line 56).
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/msteams/src/attachments/shared.ts
Line: 95-104
Comment:
**`onedrive.live.com` missing from `DEFAULT_MEDIA_HOST_ALLOWLIST`**
`onedrive.live.com` is added to `GRAPH_SHARED_LINK_HOST_SUFFIXES` here, but it does not appear in `DEFAULT_MEDIA_HOST_ALLOWLIST` (neither as an exact entry nor matched by the `"onedrive.com"` suffix, since `"onedrive.live.com".endsWith("onedrive.com")` is `false`).
In `graph.ts` (the group-chat path), `isUrlAllowed(shareUrl, policy.allowHosts)` is checked against the **original** `contentUrl` before building the `sharesUrl`. Because `onedrive.live.com` is not in the allowlist, that guard silently skips every `onedrive.live.com` reference attachment in group chats. The `download.ts` (1:1 DM) path is unaffected because `resolveDownloadCandidate` rewrites the URL to `graph.microsoft.com` before the allowlist check.
Adding `onedrive.live.com` to `GRAPH_SHARED_LINK_HOST_SUFFIXES` implies it is fully handled, but the group-chat path will drop these attachments without error. The fix requires also adding `"onedrive.live.com"` to `DEFAULT_MEDIA_HOST_ALLOWLIST` (around line 56).
How can I resolve this? If you propose a fix, please make it concise.… endpoint (openclaw#55383) (openclaw#63942) * fix(msteams): fetch OneDrive/SharePoint media via Graph shares endpoint (openclaw#55383) * fix(msteams): rewrite shared links before allowlist check * test(msteams): fix typed fetch call assertions --------- Co-authored-by: Brad Groux <bradgroux@users.noreply.github.com>
… endpoint (openclaw#55383) (openclaw#63942) * fix(msteams): fetch OneDrive/SharePoint media via Graph shares endpoint (openclaw#55383) * fix(msteams): rewrite shared links before allowlist check * test(msteams): fix typed fetch call assertions --------- Co-authored-by: Brad Groux <bradgroux@users.noreply.github.com>
… endpoint (openclaw#55383) (openclaw#63942) * fix(msteams): fetch OneDrive/SharePoint media via Graph shares endpoint (openclaw#55383) * fix(msteams): rewrite shared links before allowlist check * test(msteams): fix typed fetch call assertions --------- Co-authored-by: Brad Groux <bradgroux@users.noreply.github.com>
Summary
Files shared from OneDrive/SharePoint into Teams now resolve correctly via the Graph
/shares/{shareId}/driveItem/contentendpoint instead of returning empty content.Root cause
When a user shared a OneDrive or SharePoint file in a 1:1 Teams DM, the attachment arrived in
activity.attachmentswithcontentType: "reference"andcontentUrlpointing to a SharePoint/OneDrive landing URL. The direct-download path (downloadMSTeamsAttachments) treated it as a regular URL and fetched it directly, which returns an HTML landing page (or empty body) rather than the file bytes.The Graph fallback in
downloadMSTeamsGraphMediaalready knew how to handlereferenceattachments, but it only ran when the message also contained an HTML attachment (image/video inline paste path). 1:1 DMs with just a reference attachment never hit the working path.Fix
isGraphSharedLinkUrl,encodeGraphShareId, andtryBuildGraphSharesUrlForSharedLinkhelpers inattachments/shared.tsthat detect SharePoint/OneDrive hosts (including GCC/DoD and1drv.ms) and build theGET /shares/{u!base64url(url)}/driveItem/contentURL per the Graph spec.resolveDownloadCandidatewhen the direct attachment is a SharePoint/OneDrive shared link. The existing auth fallback infetchWithAuthFallbackalready promotes the Graph scope forgraph.microsoft.comhosts, so the rewritten request picks up the app's Graph token on auth retry.attachments/graph.tsreference-attachment branch to use the sharedencodeGraphShareIdhelper so both paths stay in sync.Fixes #55383
Test plan
isGraphSharedLinkUrlacross SharePoint (.com/.us/.cn/-df.com),1drv.ms,onedrive.live.com,onedrive.com, and negative casesencodeGraphShareIdverifyingu!prefix, base64url alphabet (no+///=), and round-triptryBuildGraphSharesUrlForSharedLinkon SharePoint, OneDrive, and non-shared URLsdownloadMSTeamsAttachmentstest confirms SharePoint / OneDrive reference attachments route throughgraph.microsoft.com/v1.0/shares/...with the Graph-scoped token